@@ -184,8 +184,6 @@ static JSValue js_printf_internal(JSContext *ctx,
184
184
int64_t int64_arg ;
185
185
double double_arg ;
186
186
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 ;
189
187
190
188
js_std_dbuf_init (ctx , & dbuf );
191
189
@@ -225,7 +223,9 @@ static JSValue js_printf_internal(JSContext *ctx,
225
223
goto missing ;
226
224
if (JS_ToInt32 (ctx , & int32_arg , argv [i ++ ]))
227
225
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 );
229
229
fmt ++ ;
230
230
} else {
231
231
while (my_isdigit (* fmt )) {
@@ -243,7 +243,9 @@ static JSValue js_printf_internal(JSContext *ctx,
243
243
goto missing ;
244
244
if (JS_ToInt32 (ctx , & int32_arg , argv [i ++ ]))
245
245
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 );
247
249
fmt ++ ;
248
250
} else {
249
251
while (my_isdigit (* fmt )) {
@@ -254,10 +256,33 @@ static JSValue js_printf_internal(JSContext *ctx,
254
256
}
255
257
}
256
258
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' ;
261
286
}
262
287
263
288
/* type */
@@ -285,10 +310,14 @@ static JSValue js_printf_internal(JSContext *ctx,
285
310
if ((unsigned )int32_arg > 0x10FFFF )
286
311
int32_arg = 0xFFFD ;
287
312
/* ignore conversion flags, width and precision */
313
+ // XXX: Hash modifier could output pretty Unicode character
314
+ // XXX: `l` length modifier is implicit
288
315
len = unicode_to_utf8 (cbuf , int32_arg );
289
316
dbuf_put (& dbuf , cbuf , len );
290
317
break ;
291
318
319
+ case 'b' :
320
+ case 'B' :
292
321
case 'd' :
293
322
case 'i' :
294
323
case 'o' :
@@ -297,40 +326,29 @@ static JSValue js_printf_internal(JSContext *ctx,
297
326
case 'X' :
298
327
if (i >= argc )
299
328
goto missing ;
329
+ // XXX: should handle BigInt values
300
330
if (JS_ToInt64Ext (ctx , & int64_arg , argv [i ++ ]))
301
331
goto fail ;
302
332
if (mod == 'l' ) {
303
333
/* 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 );
321
335
} else {
322
- dbuf_printf_fun (& dbuf , fmtbuf , (int )int64_arg );
336
+ dbuf_printf (& dbuf , fmtbuf , (int )int64_arg );
323
337
}
324
338
break ;
325
339
326
340
case 's' :
327
341
if (i >= argc )
328
342
goto missing ;
329
343
/* 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
330
348
string_arg = JS_ToCString (ctx , argv [i ++ ]);
331
349
if (!string_arg )
332
350
goto fail ;
333
- dbuf_printf_fun (& dbuf , fmtbuf , string_arg );
351
+ dbuf_printf (& dbuf , fmtbuf , string_arg );
334
352
JS_FreeCString (ctx , string_arg );
335
353
break ;
336
354
@@ -346,10 +364,12 @@ static JSValue js_printf_internal(JSContext *ctx,
346
364
goto missing ;
347
365
if (JS_ToFloat64 (ctx , & double_arg , argv [i ++ ]))
348
366
goto fail ;
349
- dbuf_printf_fun (& dbuf , fmtbuf , double_arg );
367
+ dbuf_printf (& dbuf , fmtbuf , double_arg );
350
368
break ;
351
369
352
370
case '%' :
371
+ if (q != fmtbuf + 2 ) // accept only %%
372
+ goto invalid ;
353
373
dbuf_putc (& dbuf , '%' );
354
374
break ;
355
375
0 commit comments