@@ -233,19 +233,20 @@ static Bool_t IsGoodChar(char c, TGNumberFormat::EStyle style,
233
233
234
234
// //////////////////////////////////////////////////////////////////////////////
235
235
236
- static char *EliminateGarbage (char *text,
237
- TGNumberFormat::EStyle style,
238
- TGNumberFormat::EAttribute attr)
236
+ static void CopyAndEliminateGarbage (char *dst,
237
+ std::size_t dstCap,
238
+ const char *src,
239
+ TGNumberFormat::EStyle style,
240
+ TGNumberFormat::EAttribute attr)
239
241
{
240
- if (text == 0 ) {
241
- return 0 ;
242
- }
243
- for (Int_t i = strlen (text) - 1 ; i >= 0 ; i--) {
244
- if (!IsGoodChar (text[i], style, attr)) {
245
- memmove (text + i, text + i + 1 , strlen (text) - i);
242
+ std::size_t dstIdx = 0 ;
243
+ while (dstIdx < dstCap - 1 && src) {
244
+ if (IsGoodChar (*src, style, attr)) {
245
+ dst[dstIdx++] = *src;
246
246
}
247
+ ++src;
247
248
}
248
- return text ;
249
+ dst[dstIdx] = 0 ;
249
250
}
250
251
251
252
// //////////////////////////////////////////////////////////////////////////////
@@ -266,17 +267,9 @@ static Long_t IntStr(const char *text)
266
267
267
268
// //////////////////////////////////////////////////////////////////////////////
268
269
269
- static char *StrInt (char *text, Long_t i, Int_t digits)
270
+ static char *StrInt (char *text, std:: size_t textCap, Long_t i, Int_t digits)
270
271
{
271
- snprintf (text, 250 , " %li" , TMath::Abs (i));
272
- TString s = text;
273
- while (digits > s.Length ()) {
274
- s = " 0" + s;
275
- }
276
- if (i < 0 ) {
277
- s = " -" + s;
278
- }
279
- strlcpy (text, (const char *) s, 250 );
272
+ snprintf (text, textCap, " %0*li" , digits + (i < 0 ), i);
280
273
return text;
281
274
}
282
275
@@ -285,35 +278,45 @@ static char *StrInt(char *text, Long_t i, Int_t digits)
285
278
static TString StringInt (Long_t i, Int_t digits)
286
279
{
287
280
char text[256 ];
288
- StrInt (text, i, digits);
281
+ StrInt (text, sizeof (text), i, digits);
289
282
return TString (text);
290
283
}
291
284
292
285
// //////////////////////////////////////////////////////////////////////////////
293
286
294
- static char *RealToStr (char *text, const RealInfo_t & ri)
287
+ static char *RealToStr (char *text, std:: size_t textCap, const RealInfo_t & ri)
295
288
{
296
289
char *p = text;
297
- if (text == 0 ) {
298
- return 0 ;
290
+ if (! text) {
291
+ return nullptr ;
299
292
}
300
- strlcpy (p, " " , 256 );
293
+ if (!textCap)
294
+ return text;
295
+
296
+ const auto TextLen = [&p, text, textCap] () -> std::size_t {
297
+ std::size_t curTextLen = p - text;
298
+ if (curTextLen >= textCap)
299
+ return 0 ;
300
+ return textCap - curTextLen;
301
+ };
302
+
303
+ strlcpy (p, " " , textCap);
301
304
if (ri.fSign < 0 ) {
302
- strlcpy (p, " -" , 256 );
305
+ strlcpy (p, " -" , textCap );
303
306
p++;
304
307
}
305
- StrInt (p, TMath::Abs (ri.fIntNum ), 0 );
308
+ StrInt (p, TextLen (), TMath::Abs (ri.fIntNum ), 0 );
306
309
p += strlen (p);
307
310
if ((ri.fStyle == kRSFrac ) || (ri.fStyle == kRSFracExpo )) {
308
- strlcpy (p, " ." , 256 - strlen (text ));
311
+ strlcpy (p, " ." , TextLen ( ));
309
312
p++;
310
- StrInt (p, TMath::Abs (ri.fFracNum ), ri.fFracDigits );
313
+ StrInt (p, TextLen (), TMath::Abs (ri.fFracNum ), ri.fFracDigits );
311
314
p += strlen (p);
312
315
}
313
316
if ((ri.fStyle == kRSExpo ) || (ri.fStyle == kRSFracExpo )) {
314
- strlcpy (p, " e" , 256 - strlen (text ));
317
+ strlcpy (p, " e" , TextLen ( ));
315
318
p++;
316
- StrInt (p, ri.fExpoNum , 0 );
319
+ StrInt (p, TextLen (), ri.fExpoNum , 0 );
317
320
p += strlen (p);
318
321
}
319
322
return text;
@@ -436,30 +439,15 @@ static ULong_t HexStrToInt(const char *s)
436
439
437
440
// //////////////////////////////////////////////////////////////////////////////
438
441
439
- static char *IntToHexStr (char *text, ULong_t l)
442
+ static char *IntToHexStr (char *text, std:: size_t textCap, ULong_t l)
440
443
{
441
- const char *const digits = " 0123456789ABCDEF" ;
442
- char buf[64 ];
443
- char *p = buf + 62 ;
444
- // coverity[secure_coding]
445
- strcpy (p, " " );
446
- while (l > 0 ) {
447
- *(--p) = digits[l % 16 ];
448
- l /= 16 ;
449
- }
450
- if (!p[0 ]) {
451
- // coverity[secure_coding]
452
- strcpy (text, " 0" );
453
- } else {
454
- // coverity[secure_coding]
455
- strcpy (text, p);
456
- }
444
+ snprintf (text, textCap, " %lX" , l);
457
445
return text;
458
446
}
459
447
460
448
// //////////////////////////////////////////////////////////////////////////////
461
449
462
- static char *MIntToStr (char *text, Long_t l, Int_t digits)
450
+ static char *MIntToStr (char *text, std:: size_t textCap, Long_t l, Int_t digits)
463
451
{
464
452
TString s;
465
453
Int_t base;
@@ -486,13 +474,13 @@ static char *MIntToStr(char *text, Long_t l, Int_t digits)
486
474
if (l < 0 ) {
487
475
s = " -" + s;
488
476
}
489
- strlcpy (text, (const char *) s, 256 );
477
+ strlcpy (text, (const char *) s, textCap );
490
478
return text;
491
479
}
492
480
493
481
// //////////////////////////////////////////////////////////////////////////////
494
482
495
- static char *DIntToStr (char *text, Long_t l, Bool_t Sec, char Del)
483
+ static char *DIntToStr (char *text, std:: size_t textCap, Long_t l, Bool_t Sec, char Del)
496
484
{
497
485
TString s;
498
486
if (Sec) {
@@ -506,14 +494,14 @@ static char *DIntToStr(char *text, Long_t l, Bool_t Sec, char Del)
506
494
if (l < 0 ) {
507
495
s = " -" + s;
508
496
}
509
- strlcpy (text, (const char *) s, 256 );
497
+ strlcpy (text, (const char *) s, textCap );
510
498
return text;
511
499
}
512
500
513
501
// //////////////////////////////////////////////////////////////////////////////
514
502
// / For kNESMinSecCent
515
503
516
- static char *DIntToStr (char *text, Long_t l, char Del, char Del2)
504
+ static char *DIntToStr (char *text, std:: size_t textCap, Long_t l, char Del, char Del2)
517
505
{
518
506
TString s;
519
507
s = StringInt (TMath::Abs (l) / 6000 , 0 ) + Del +
@@ -522,7 +510,7 @@ static char *DIntToStr(char *text, Long_t l, char Del, char Del2)
522
510
if (l < 0 ) {
523
511
s = " -" + s;
524
512
}
525
- strlcpy (text, (const char *) s, 256 );
513
+ strlcpy (text, (const char *) s, textCap );
526
514
return text;
527
515
}
528
516
@@ -574,27 +562,33 @@ static Long_t GetSignificant(Long_t l, Int_t Max)
574
562
575
563
// //////////////////////////////////////////////////////////////////////////////
576
564
577
- static void AppendFracZero (char *text, Int_t digits)
565
+ // / Given a numeric string "xxx.yyy" or "xxx,yyy", makes sure that the fractional
566
+ // / part (if present) always has at least `digits` digits, appending zeroes if needed.
567
+ static void AppendFracZero (char *text, std::size_t textCap, Int_t digits)
578
568
{
579
- char *p;
580
569
Int_t found = 0 ;
581
- p = strchr (text, ' .' );
582
- if (p == 0 ) {
583
- p = strchr (text, ' ,' );
570
+ char * p = strrchr (text, ' .' );
571
+ if (!p ) {
572
+ p = strrchr (text, ' ,' );
584
573
}
585
- if (p == 0 ) {
574
+ if (!p ) {
586
575
return ;
587
576
}
588
577
p++;
589
- for (UInt_t i = 0 ; i < strlen (p); i++) {
590
- if (isdigit (*p)) {
591
- found++;
592
- }
578
+ auto pLen = strlen (p);
579
+ for (UInt_t i = 0 ; i < pLen; i++) {
580
+ // NOTE: converting to bool because isdigit doesn't technically necessarily return 0 or 1
581
+ // (the specs mention it returns "a nonzero value" for positive cases).
582
+ found += !!isdigit (p[i]);
593
583
}
594
- while (found < digits) {
595
- // coverity[secure_coding]
596
- strcpy (p + strlen (p), " 0" );
597
- found++;
584
+ auto pOff = p - text;
585
+ assert (textCap>= pOff + pLen);
586
+ auto remainingCap = textCap - pOff - pLen;
587
+ const auto trailingZeroes = std::min<std::size_t >(std::max (0 , digits - found), remainingCap - 1 );
588
+ if (trailingZeroes > 0 ) {
589
+ memset (p + pLen, ' 0' , trailingZeroes);
590
+ // ensure the new string is null terminated
591
+ p[pLen + trailingZeroes] = 0 ;
598
592
}
599
593
}
600
594
@@ -646,23 +640,23 @@ static Long_t TranslateToNum(const char *text,
646
640
{
647
641
char buf[256 ];
648
642
strlcpy (buf, text, sizeof (buf));
649
- AppendFracZero (buf, 2 );
643
+ AppendFracZero (buf, sizeof (buf), 2 );
650
644
GetNumbers (buf, sign, n1, 12 , n2, 2 , n3, 0 , " .," );
651
645
return sign * (100 * n1 + GetSignificant (n2, 100 ));
652
646
}
653
647
case TGNumberFormat::kNESRealThree :
654
648
{
655
649
char buf[256 ];
656
650
strlcpy (buf, text, sizeof (buf));
657
- AppendFracZero (buf, 3 );
651
+ AppendFracZero (buf, sizeof (buf), 3 );
658
652
GetNumbers (buf, sign, n1, 12 , n2, 3 , n3, 0 , " .," );
659
653
return sign * (1000 * n1 + GetSignificant (n2, 1000 ));
660
654
}
661
655
case TGNumberFormat::kNESRealFour :
662
656
{
663
657
char buf[256 ];
664
658
strlcpy (buf, text, sizeof (buf));
665
- AppendFracZero (buf, 4 );
659
+ AppendFracZero (buf, sizeof (buf), 4 );
666
660
GetNumbers (buf, sign, n1, 12 , n2, 4 , n3, 0 , " .," );
667
661
return sign * (10000 * n1 + GetSignificant (n2, 10000 ));
668
662
}
@@ -700,40 +694,41 @@ static Long_t TranslateToNum(const char *text,
700
694
701
695
// //////////////////////////////////////////////////////////////////////////////
702
696
// / Translate a number value to a string.
697
+ // / `textCap` indicates the capacity of `text`.
703
698
704
- static char *TranslateToStr (char *text, Long_t l,
699
+ static char *TranslateToStr (char *text, std:: size_t textCap, Long_t l,
705
700
TGNumberFormat::EStyle style, const RealInfo_t & ri)
706
701
{
707
702
switch (style) {
708
703
case TGNumberFormat::kNESInteger :
709
- return StrInt (text, l, 0 );
704
+ return StrInt (text, textCap, l, 0 );
710
705
case TGNumberFormat::kNESRealOne :
711
- return MIntToStr (text, l, 1 );
706
+ return MIntToStr (text, textCap, l, 1 );
712
707
case TGNumberFormat::kNESRealTwo :
713
- return MIntToStr (text, l, 2 );
708
+ return MIntToStr (text, textCap, l, 2 );
714
709
case TGNumberFormat::kNESRealThree :
715
- return MIntToStr (text, l, 3 );
710
+ return MIntToStr (text, textCap, l, 3 );
716
711
case TGNumberFormat::kNESRealFour :
717
- return MIntToStr (text, l, 4 );
712
+ return MIntToStr (text, textCap, l, 4 );
718
713
case TGNumberFormat::kNESReal :
719
- return RealToStr (text, ri);
714
+ return RealToStr (text, textCap, ri);
720
715
case TGNumberFormat::kNESDegree :
721
- return DIntToStr (text, l, kTRUE , ' .' );
716
+ return DIntToStr (text, textCap, l, kTRUE , ' .' );
722
717
case TGNumberFormat::kNESHourMinSec :
723
- return DIntToStr (text, l % (24 * 3600 ), kTRUE , ' :' );
718
+ return DIntToStr (text, textCap, l % (24 * 3600 ), kTRUE , ' :' );
724
719
case TGNumberFormat::kNESMinSec :
725
- return DIntToStr (text, l, kFALSE , ' :' );
720
+ return DIntToStr (text, textCap, l, kFALSE , ' :' );
726
721
case TGNumberFormat::kNESMinSecCent :
727
- return DIntToStr (text, l % (60 * 6000 ), ' :' , ' .' );
722
+ return DIntToStr (text, textCap, l % (60 * 6000 ), ' :' , ' .' );
728
723
case TGNumberFormat::kNESHourMin :
729
- return DIntToStr (text, l % (24 * 60 ), kFALSE , ' :' );
724
+ return DIntToStr (text, textCap, l % (24 * 60 ), kFALSE , ' :' );
730
725
case TGNumberFormat::kNESDayMYear :
731
726
{
732
727
TString date =
733
728
StringInt (TMath::Abs (l) % 100 , 0 ) + " /" +
734
729
StringInt ((TMath::Abs (l) / 100 ) % 100 , 0 ) + " /" +
735
730
StringInt (TMath::Abs (l) / 10000 , 0 );
736
- strlcpy (text, (const char *) date, 256 );
731
+ strlcpy (text, (const char *) date, textCap );
737
732
return text;
738
733
}
739
734
case TGNumberFormat::kNESMDayYear :
@@ -742,11 +737,11 @@ static char *TranslateToStr(char *text, Long_t l,
742
737
StringInt ((TMath::Abs (l) / 100 ) % 100 , 0 ) + " /" +
743
738
StringInt (TMath::Abs (l) % 100 , 0 ) + " /" +
744
739
StringInt (TMath::Abs (l) / 10000 , 0 );
745
- strlcpy (text, (const char *) date, 256 );
740
+ strlcpy (text, (const char *) date, textCap );
746
741
return text;
747
742
}
748
743
case TGNumberFormat::kNESHex :
749
- return IntToHexStr (text, (ULong_t) l);
744
+ return IntToHexStr (text, textCap, (ULong_t) l);
750
745
}
751
746
return 0 ;
752
747
}
@@ -1200,9 +1195,9 @@ void TGNumberEntryField::SetIntNumber(Long_t val, Bool_t emit)
1200
1195
char text[256 ];
1201
1196
RealInfo_t ri;
1202
1197
if (fNumStyle == kNESReal ) {
1203
- TranslateToStr (text, val, kNESInteger , ri);
1198
+ TranslateToStr (text, sizeof (text), val, kNESInteger , ri);
1204
1199
} else {
1205
- TranslateToStr (text, val, fNumStyle , ri);
1200
+ TranslateToStr (text, sizeof (text), val, fNumStyle , ri);
1206
1201
}
1207
1202
SetText (text, emit);
1208
1203
}
@@ -1265,8 +1260,7 @@ void TGNumberEntryField::SetHexNumber(ULong_t val, Bool_t emit)
1265
1260
void TGNumberEntryField::SetText (const char *text, Bool_t emit)
1266
1261
{
1267
1262
char buf[256 ];
1268
- strlcpy (buf, text, sizeof (buf));
1269
- EliminateGarbage (buf, fNumStyle , fNumAttr );
1263
+ CopyAndEliminateGarbage (buf, sizeof (buf), text, fNumStyle , fNumAttr );
1270
1264
TGTextEntry::SetText (buf, emit);
1271
1265
fNeedsVerification = kFALSE ;
1272
1266
}
@@ -1617,7 +1611,7 @@ void TGNumberEntryField::IncreaseNumber(EStepSize step,
1617
1611
SetIntNumber (l);
1618
1612
} else {
1619
1613
char buf[256 ];
1620
- RealToStr (buf, ri);
1614
+ RealToStr (buf, sizeof (buf), ri);
1621
1615
SetText (buf);
1622
1616
}
1623
1617
}
@@ -2253,7 +2247,7 @@ void TGNumberEntry::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
2253
2247
break ;
2254
2248
case kNESHex : {
2255
2249
char hexstr[256 ];
2256
- IntToHexStr (hexstr, GetHexNumber ());
2250
+ IntToHexStr (hexstr, sizeof (hexstr), GetHexNumber ());
2257
2251
out << " 0x" << hexstr << " U, " << digits << " , " << WidgetId () << " ,(TGNumberFormat::EStyle) " << GetNumStyle ();
2258
2252
break ;
2259
2253
}
@@ -2323,7 +2317,7 @@ void TGNumberEntryField::SavePrimitive(std::ostream &out, Option_t *option /*= "
2323
2317
case kNESMDayYear : out << yy << mm << dd << " ,(TGNumberFormat::EStyle) " << GetNumStyle (); break ;
2324
2318
case kNESHex : {
2325
2319
char hexstr[256 ];
2326
- IntToHexStr (hexstr, GetHexNumber ());
2320
+ IntToHexStr (hexstr, sizeof (hexstr), GetHexNumber ());
2327
2321
out << " 0x" << hexstr << " U, (TGNumberFormat::EStyle) " << GetNumStyle ();
2328
2322
break ;
2329
2323
}
0 commit comments