@@ -184,8 +184,6 @@ static JSValue js_printf_internal(JSContext *ctx,
184184 int64_t int64_arg ;
185185 double double_arg ;
186186 const char * string_arg ;
187- /* Use indirect call to dbuf_printf to prevent gcc warning */
188- int (* dbuf_printf_fun )(DynBuf * s , const char * fmt , ...) = (void * )dbuf_printf ;
189187
190188 js_std_dbuf_init (ctx , & dbuf );
191189
@@ -225,7 +223,9 @@ static JSValue js_printf_internal(JSContext *ctx,
225223 goto missing ;
226224 if (JS_ToInt32 (ctx , & int32_arg , argv [i ++ ]))
227225 goto fail ;
228- q += snprintf (q , fmtbuf + sizeof (fmtbuf ) - q , "%d" , int32_arg );
226+ if (q > fmtbuf + sizeof (fmtbuf ) - 11 )
227+ goto invalid ;
228+ q += i32toa (q , int32_arg );
229229 fmt ++ ;
230230 } else {
231231 while (my_isdigit (* fmt )) {
@@ -243,7 +243,9 @@ static JSValue js_printf_internal(JSContext *ctx,
243243 goto missing ;
244244 if (JS_ToInt32 (ctx , & int32_arg , argv [i ++ ]))
245245 goto fail ;
246- q += snprintf (q , fmtbuf + sizeof (fmtbuf ) - q , "%d" , int32_arg );
246+ if (q > fmtbuf + sizeof (fmtbuf ) - 11 )
247+ goto invalid ;
248+ q += i32toa (q , int32_arg );
247249 fmt ++ ;
248250 } else {
249251 while (my_isdigit (* fmt )) {
@@ -254,10 +256,33 @@ static JSValue js_printf_internal(JSContext *ctx,
254256 }
255257 }
256258
257- /* we only support the "l" modifier for 64 bit numbers */
258- mod = ' ' ;
259- if (* fmt == 'l' ) {
260- mod = * fmt ++ ;
259+ /* we only support the "l" modifier for 64 bit numbers
260+ and the w# length modifier with a bitlength of 1 to 64
261+ */
262+ // XXX: should use value changing conversions
263+ mod = * fmt ;
264+ if (mod == 'w' ) {
265+ int bitwidth ;
266+ if (q >= fmtbuf + sizeof (fmtbuf ) - 4 )
267+ goto invalid ;
268+ * q ++ = * fmt ++ ;
269+ if (!(* fmt >= '1' && * fmt <= '9' ))
270+ goto invalid ;
271+ bitwidth = * fmt - '0' ;
272+ * q ++ = * fmt ++ ;
273+ if (* fmt >= '0' && * fmt <= '9' ) {
274+ bitwidth = bitwidth * 10 + * fmt - '0' ;
275+ * q ++ = * fmt ++ ;
276+ }
277+ if (bitwidth > 32 )
278+ mod = 'l' ;
279+ } else
280+ if (mod == 'l' ) {
281+ fmt ++ ;
282+ if (q >= fmtbuf + sizeof (fmtbuf ) - 3 )
283+ goto invalid ;
284+ * q ++ = 'l' ;
285+ * q ++ = 'l' ;
261286 }
262287
263288 /* type */
@@ -285,10 +310,14 @@ static JSValue js_printf_internal(JSContext *ctx,
285310 if ((unsigned )int32_arg > 0x10FFFF )
286311 int32_arg = 0xFFFD ;
287312 /* ignore conversion flags, width and precision */
313+ // XXX: Hash modifier could output pretty Unicode character
314+ // XXX: `l` length modifier is implicit
288315 len = unicode_to_utf8 (cbuf , int32_arg );
289316 dbuf_put (& dbuf , cbuf , len );
290317 break ;
291318
319+ case 'b' :
320+ case 'B' :
292321 case 'd' :
293322 case 'i' :
294323 case 'o' :
@@ -297,40 +326,29 @@ static JSValue js_printf_internal(JSContext *ctx,
297326 case 'X' :
298327 if (i >= argc )
299328 goto missing ;
329+ // XXX: should handle BigInt values
300330 if (JS_ToInt64Ext (ctx , & int64_arg , argv [i ++ ]))
301331 goto fail ;
302332 if (mod == 'l' ) {
303333 /* 64 bit number */
304- #if defined(_WIN32 )
305- if (q >= fmtbuf + sizeof (fmtbuf ) - 3 )
306- goto invalid ;
307- q [2 ] = q [-1 ];
308- q [-1 ] = 'I' ;
309- q [0 ] = '6' ;
310- q [1 ] = '4' ;
311- q [3 ] = '\0' ;
312- dbuf_printf_fun (& dbuf , fmtbuf , (int64_t )int64_arg );
313- #else
314- if (q >= fmtbuf + sizeof (fmtbuf ) - 2 )
315- goto invalid ;
316- q [1 ] = q [-1 ];
317- q [-1 ] = q [0 ] = 'l' ;
318- q [2 ] = '\0' ;
319- dbuf_printf_fun (& dbuf , fmtbuf , (long long )int64_arg );
320- #endif
334+ dbuf_printf (& dbuf , fmtbuf , (int64_t )int64_arg );
321335 } else {
322- dbuf_printf_fun (& dbuf , fmtbuf , (int )int64_arg );
336+ dbuf_printf (& dbuf , fmtbuf , (int )int64_arg );
323337 }
324338 break ;
325339
326340 case 's' :
327341 if (i >= argc )
328342 goto missing ;
329343 /* XXX: handle strings containing null characters */
344+ // XXX: # could output encoded string
345+ // XXX: null values should output as `<null>`
346+ // XXX: undefined values should output as `<undefined>`
347+ // XXX: `l` length modifier is implicit
330348 string_arg = JS_ToCString (ctx , argv [i ++ ]);
331349 if (!string_arg )
332350 goto fail ;
333- dbuf_printf_fun (& dbuf , fmtbuf , string_arg );
351+ dbuf_printf (& dbuf , fmtbuf , string_arg );
334352 JS_FreeCString (ctx , string_arg );
335353 break ;
336354
@@ -346,10 +364,12 @@ static JSValue js_printf_internal(JSContext *ctx,
346364 goto missing ;
347365 if (JS_ToFloat64 (ctx , & double_arg , argv [i ++ ]))
348366 goto fail ;
349- dbuf_printf_fun (& dbuf , fmtbuf , double_arg );
367+ dbuf_printf (& dbuf , fmtbuf , double_arg );
350368 break ;
351369
352370 case '%' :
371+ if (q != fmtbuf + 2 ) // accept only %%
372+ goto invalid ;
353373 dbuf_putc (& dbuf , '%' );
354374 break ;
355375
0 commit comments