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