@@ -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