14
14
15
15
namespace scudo {
16
16
17
- static int appendChar (char **Buffer, const char *BufferEnd, char C) {
18
- if (*Buffer < BufferEnd) {
19
- **Buffer = C;
20
- (*Buffer)++;
21
- }
22
- return 1 ;
23
- }
24
-
25
17
// Appends number in a given Base to buffer. If its length is less than
26
18
// |MinNumberLength|, it is padded with leading zeroes or spaces, depending
27
19
// on the value of |PadWithZero|.
28
- static int appendNumber (char **Buffer, const char *BufferEnd, u64 AbsoluteValue,
29
- u8 Base, u8 MinNumberLength, bool PadWithZero,
30
- bool Negative, bool Upper) {
20
+ void ScopedString::appendNumber (u64 AbsoluteValue, u8 Base, u8 MinNumberLength,
21
+ bool PadWithZero, bool Negative, bool Upper) {
31
22
constexpr uptr MaxLen = 30 ;
32
23
RAW_CHECK (Base == 10 || Base == 16 );
33
24
RAW_CHECK (Base == 10 || !Negative);
34
25
RAW_CHECK (AbsoluteValue || !Negative);
35
26
RAW_CHECK (MinNumberLength < MaxLen);
36
- int Res = 0 ;
37
27
if (Negative && MinNumberLength)
38
28
--MinNumberLength;
39
- if (Negative && PadWithZero)
40
- Res += appendChar (Buffer, BufferEnd, ' -' );
29
+ if (Negative && PadWithZero) {
30
+ String.push_back (' -' );
31
+ }
41
32
uptr NumBuffer[MaxLen];
42
33
int Pos = 0 ;
43
34
do {
@@ -55,79 +46,78 @@ static int appendNumber(char **Buffer, const char *BufferEnd, u64 AbsoluteValue,
55
46
Pos--;
56
47
for (; Pos >= 0 && NumBuffer[Pos] == 0 ; Pos--) {
57
48
char c = (PadWithZero || Pos == 0 ) ? ' 0' : ' ' ;
58
- Res += appendChar (Buffer, BufferEnd, c);
49
+ String. push_back ( c);
59
50
}
60
51
if (Negative && !PadWithZero)
61
- Res += appendChar (Buffer, BufferEnd, ' -' );
52
+ String. push_back ( ' -' );
62
53
for (; Pos >= 0 ; Pos--) {
63
54
char Digit = static_cast <char >(NumBuffer[Pos]);
64
55
Digit = static_cast <char >((Digit < 10 ) ? ' 0' + Digit
65
56
: (Upper ? ' A' : ' a' ) + Digit - 10 );
66
- Res += appendChar (Buffer, BufferEnd, Digit);
57
+ String. push_back ( Digit);
67
58
}
68
- return Res;
69
59
}
70
60
71
- static int appendUnsigned (char **Buffer, const char *BufferEnd, u64 Num,
72
- u8 Base, u8 MinNumberLength, bool PadWithZero,
73
- bool Upper) {
74
- return appendNumber (Buffer, BufferEnd, Num, Base, MinNumberLength,
75
- PadWithZero, /* Negative=*/ false , Upper);
61
+ void ScopedString::appendUnsigned (u64 Num, u8 Base, u8 MinNumberLength,
62
+ bool PadWithZero, bool Upper) {
63
+ appendNumber (Num, Base, MinNumberLength, PadWithZero, /* Negative=*/ false ,
64
+ Upper);
76
65
}
77
66
78
- static int appendSignedDecimal (char **Buffer, const char *BufferEnd, s64 Num ,
79
- u8 MinNumberLength, bool PadWithZero) {
67
+ void ScopedString:: appendSignedDecimal (s64 Num, u8 MinNumberLength ,
68
+ bool PadWithZero) {
80
69
const bool Negative = (Num < 0 );
81
70
const u64 UnsignedNum = (Num == INT64_MIN)
82
71
? static_cast <u64 >(INT64_MAX) + 1
83
72
: static_cast <u64 >(Negative ? -Num : Num);
84
- return appendNumber (Buffer, BufferEnd, UnsignedNum, 10 , MinNumberLength ,
85
- PadWithZero, Negative, /* Upper=*/ false );
73
+ appendNumber (UnsignedNum, 10 , MinNumberLength, PadWithZero, Negative ,
74
+ /* Upper=*/ false );
86
75
}
87
76
88
77
// Use the fact that explicitly requesting 0 Width (%0s) results in UB and
89
78
// interpret Width == 0 as "no Width requested":
90
79
// Width == 0 - no Width requested
91
80
// Width < 0 - left-justify S within and pad it to -Width chars, if necessary
92
81
// Width > 0 - right-justify S, not implemented yet
93
- static int appendString (char **Buffer, const char *BufferEnd, int Width,
94
- int MaxChars, const char *S) {
82
+ void ScopedString::appendString (int Width, int MaxChars, const char *S) {
95
83
if (!S)
96
84
S = " <null>" ;
97
- int Res = 0 ;
85
+ int NumChars = 0 ;
98
86
for (; *S; S++) {
99
- if (MaxChars >= 0 && Res >= MaxChars)
87
+ if (MaxChars >= 0 && NumChars >= MaxChars)
100
88
break ;
101
- Res += appendChar (Buffer, BufferEnd, *S);
89
+ String.push_back (*S);
90
+ NumChars++;
91
+ }
92
+ if (Width < 0 ) {
93
+ // Only left justification supported.
94
+ Width = -Width - NumChars;
95
+ while (Width-- > 0 )
96
+ String.push_back (' ' );
102
97
}
103
- // Only the left justified strings are supported.
104
- while (Width < -Res)
105
- Res += appendChar (Buffer, BufferEnd, ' ' );
106
- return Res;
107
98
}
108
99
109
- static int appendPointer (char **Buffer, const char *BufferEnd, u64 ptr_value) {
110
- int Res = 0 ;
111
- Res += appendString (Buffer, BufferEnd, 0 , -1 , " 0x" );
112
- Res += appendUnsigned (Buffer, BufferEnd, ptr_value, 16 ,
113
- SCUDO_POINTER_FORMAT_LENGTH, /* PadWithZero=*/ true ,
114
- /* Upper=*/ false );
115
- return Res;
100
+ void ScopedString::appendPointer (u64 ptr_value) {
101
+ appendString (0 , -1 , " 0x" );
102
+ appendUnsigned (ptr_value, 16 , SCUDO_POINTER_FORMAT_LENGTH,
103
+ /* PadWithZero=*/ true ,
104
+ /* Upper=*/ false );
116
105
}
117
106
118
- static int formatString (char *Buffer, uptr BufferLength, const char *Format,
119
- va_list Args) {
107
+ void ScopedString::vappend (const char *Format, va_list &Args) {
108
+ // Since the string contains the '\0' terminator, put our size before it
109
+ // so that push_back calls work correctly.
110
+ DCHECK (String.size () > 0 );
111
+ String.resize (String.size () - 1 );
112
+
120
113
static const char *PrintfFormatsHelp =
121
- " Supported formatString formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; "
114
+ " Supported formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; "
122
115
" %[-]([0-9]*)?(\\ .\\ *)?s; %c\n " ;
123
116
RAW_CHECK (Format);
124
- RAW_CHECK (BufferLength > 0 );
125
- const char *BufferEnd = &Buffer[BufferLength - 1 ];
126
117
const char *Cur = Format;
127
- int Res = 0 ;
128
118
for (; *Cur; Cur++) {
129
119
if (*Cur != ' %' ) {
130
- Res += appendChar (&Buffer, BufferEnd, *Cur);
120
+ String. push_back ( *Cur);
131
121
continue ;
132
122
}
133
123
Cur++;
@@ -162,7 +152,7 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format,
162
152
DVal = HaveLL ? va_arg (Args, s64)
163
153
: HaveZ ? va_arg (Args, sptr)
164
154
: va_arg (Args, int );
165
- Res += appendSignedDecimal (&Buffer, BufferEnd, DVal, Width, PadWithZero);
155
+ appendSignedDecimal (DVal, Width, PadWithZero);
166
156
break ;
167
157
}
168
158
case ' u' :
@@ -172,27 +162,25 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format,
172
162
: HaveZ ? va_arg (Args, uptr)
173
163
: va_arg (Args, unsigned );
174
164
const bool Upper = (*Cur == ' X' );
175
- Res += appendUnsigned (&Buffer, BufferEnd, UVal, (*Cur == ' u' ) ? 10 : 16 ,
176
- Width, PadWithZero, Upper);
165
+ appendUnsigned (UVal, (*Cur == ' u' ) ? 10 : 16 , Width, PadWithZero, Upper);
177
166
break ;
178
167
}
179
168
case ' p' : {
180
169
RAW_CHECK_MSG (!HaveFlags, PrintfFormatsHelp);
181
- Res += appendPointer (&Buffer, BufferEnd, va_arg (Args, uptr));
170
+ appendPointer (va_arg (Args, uptr));
182
171
break ;
183
172
}
184
173
case ' s' : {
185
174
RAW_CHECK_MSG (!HaveLength, PrintfFormatsHelp);
186
175
// Only left-justified Width is supported.
187
176
CHECK (!HaveWidth || LeftJustified);
188
- Res += appendString (&Buffer, BufferEnd, LeftJustified ? -Width : Width,
189
- Precision, va_arg (Args, char *));
177
+ appendString (LeftJustified ? -Width : Width, Precision ,
178
+ va_arg (Args, char *));
190
179
break ;
191
180
}
192
181
case ' c' : {
193
182
RAW_CHECK_MSG (!HaveFlags, PrintfFormatsHelp);
194
- Res +=
195
- appendChar (&Buffer, BufferEnd, static_cast <char >(va_arg (Args, int )));
183
+ String.push_back (static_cast <char >(va_arg (Args, int )));
196
184
break ;
197
185
}
198
186
// In Scudo, `s64`/`u64` are supposed to use `lld` and `llu` respectively.
@@ -207,55 +195,31 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format,
207
195
208
196
if (*Cur == ' d' ) {
209
197
DVal = va_arg (Args, s64);
210
- Res +=
211
- appendSignedDecimal (&Buffer, BufferEnd, DVal, Width, PadWithZero);
198
+ appendSignedDecimal (DVal, Width, PadWithZero);
212
199
} else {
213
200
UVal = va_arg (Args, u64 );
214
- Res += appendUnsigned (&Buffer, BufferEnd, UVal, 10 , Width, PadWithZero,
215
- false );
201
+ appendUnsigned (UVal, 10 , Width, PadWithZero, false );
216
202
}
217
203
218
204
break ;
219
205
}
220
206
case ' %' : {
221
207
RAW_CHECK_MSG (!HaveFlags, PrintfFormatsHelp);
222
- Res += appendChar (&Buffer, BufferEnd, ' %' );
208
+ String. push_back ( ' %' );
223
209
break ;
224
210
}
225
211
default : {
226
212
RAW_CHECK_MSG (false , PrintfFormatsHelp);
227
213
}
228
214
}
229
215
}
230
- RAW_CHECK (Buffer <= BufferEnd);
231
- appendChar (&Buffer, BufferEnd + 1 , ' \0 ' );
232
- return Res;
233
- }
234
-
235
- int formatString (char *Buffer, uptr BufferLength, const char *Format, ...) {
236
- va_list Args;
237
- va_start (Args, Format);
238
- int Res = formatString (Buffer, BufferLength, Format, Args);
239
- va_end (Args);
240
- return Res;
241
- }
242
-
243
- void ScopedString::vappend (const char *Format, va_list Args) {
244
- va_list ArgsCopy;
245
- va_copy (ArgsCopy, Args);
246
- // formatString doesn't currently support a null buffer or zero buffer length,
247
- // so in order to get the resulting formatted string length, we use a one-char
248
- // buffer.
249
- char C[1 ];
250
- const uptr AdditionalLength =
251
- static_cast <uptr>(formatString (C, sizeof (C), Format, Args)) + 1 ;
252
- const uptr Length = length ();
253
- String.resize (Length + AdditionalLength);
254
- const uptr FormattedLength = static_cast <uptr>(formatString (
255
- String.data () + Length, String.size () - Length, Format, ArgsCopy));
256
- RAW_CHECK (data ()[length ()] == ' \0 ' );
257
- RAW_CHECK (FormattedLength + 1 == AdditionalLength);
258
- va_end (ArgsCopy);
216
+ String.push_back (' \0 ' );
217
+ if (String.back () != ' \0 ' ) {
218
+ // String truncated, make sure the string is terminated properly.
219
+ // This can happen if there is no more memory when trying to resize
220
+ // the string.
221
+ String.back () = ' \0 ' ;
222
+ }
259
223
}
260
224
261
225
void ScopedString::append (const char *Format, ...) {
0 commit comments