Skip to content

Commit c8ec22d

Browse files
committed
Use separate va_lists in PyTruffle_Unicode_FromFormat
1 parent 5442fd4 commit c8ec22d

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

graalpython/com.oracle.graal.python.cext/src/unicodeobject.c

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,8 @@ PyObject * PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size) {
230230
return to_sulong(polyglot_from_string_n(u, size, SRC_CS));
231231
}
232232

233-
#define AS_I64(__arg__) (polyglot_fits_in_i64((__arg__)) ? polyglot_as_i64((__arg__)) : (int64_t)(__arg__))
234-
235233
MUST_INLINE PyObject* PyTruffle_Unicode_FromFormat(const char *fmt, va_list va) {
234+
va_list vacpy;
236235
size_t fmt_size = strlen(fmt) + 1;
237236
char* fmtcpy = strdup(fmt);
238237
char* c = fmtcpy;
@@ -242,22 +241,25 @@ MUST_INLINE PyObject* PyTruffle_Unicode_FromFormat(const char *fmt, va_list va)
242241
char* full_buffer = buffer;
243242

244243
void *variable = NULL;
244+
PyObject *tmp = NULL;
245245
char *allocated = NULL; // points to the same as variable, if it has to be free'd
246246

247+
va_copy(vacpy, va);
248+
247249
while (c[0]) {
248250
if (c[0] == '%') {
249251
// we've reached the next directive, write until here
250252
c[0] = '\0';
251253
int bytes_written;
252254
if (variable != NULL) {
253-
bytes_written = snprintf(buffer, remaining_space, fmtcpy, AS_I64(variable));
255+
bytes_written = snprintf(buffer, remaining_space, fmtcpy, variable);
254256
if (allocated != NULL) {
255257
free(allocated);
256258
allocated = NULL;
257259
}
258260
variable = NULL;
259261
} else {
260-
bytes_written = vsnprintf(buffer, remaining_space, fmtcpy, va);
262+
bytes_written = vsnprintf(buffer, remaining_space, fmtcpy, vacpy);
261263
}
262264
remaining_space -= bytes_written;
263265
buffer += bytes_written;
@@ -278,18 +280,64 @@ MUST_INLINE PyObject* PyTruffle_Unicode_FromFormat(const char *fmt, va_list va)
278280
case 'R':
279281
if (converter == NULL) converter = PyObject_Repr;
280282
c[1] = 's';
281-
allocated = variable = as_char_pointer(converter(va_arg(va, PyObject*)));
283+
tmp = va_arg(va, PyObject*);
284+
// just advance cursor on 'vacpy'
285+
va_arg(vacpy, PyObject*);
286+
allocated = variable = as_char_pointer(converter(tmp));
282287
break;
288+
case 'c':
289+
// This case should just treat it's argument as an integer
290+
c[1] = 'd';
291+
// intentionally fall-through
283292
case 'd':
284-
break;
293+
case 'i':
294+
case 'x':
295+
// just advance cursor on 'va'
296+
va_arg(va, int);
297+
break;
298+
case 'u':
299+
// just advance cursor on 'va'
300+
va_arg(va, unsigned int);
301+
break;
302+
case 'l':
303+
// 'c[2]' is guaranteed to be a correct memory access since
304+
// it will in the worst case be '\0'.
305+
switch (c[2]) {
306+
// %ld, %li
307+
case 'd':
308+
case 'i':
309+
// just advance cursor on 'va'
310+
va_arg(va, long);
311+
break;
312+
// %lu
313+
case 'u':
314+
// just advance cursor on 'va'
315+
va_arg(va, unsigned long);
316+
// %ll?
317+
case 'l':
318+
// just advance cursor on 'va'
319+
va_arg(va, long long);
320+
}
321+
break;
322+
case 'z':
323+
// just advance cursor on 'va'
324+
va_arg(va, Py_ssize_t);
325+
break;
326+
case 's':
327+
// just advance cursor on 'va'
328+
va_arg(va, char*);
329+
break;
330+
case 'p':
331+
// just advance cursor on 'va'
332+
va_arg(va, void*);
333+
break;
285334
case '%':
286335
// literal %
287336
break;
288-
case 'c':
289-
// This case should just treat it's argument as an integer
290-
c[1] = 'd';
291337
default:
292338
variable = va_arg(va, PyObject*);
339+
// just advance cursor on 'vacpy'
340+
va_arg(vacpy, PyObject*);
293341
}
294342
// skip over next char, we checked it
295343
c += 1;
@@ -299,16 +347,17 @@ MUST_INLINE PyObject* PyTruffle_Unicode_FromFormat(const char *fmt, va_list va)
299347

300348
// write the remaining buffer
301349
if (variable != NULL) {
302-
snprintf(buffer, remaining_space, fmtcpy, AS_I64(variable));
350+
snprintf(buffer, remaining_space, fmtcpy, variable);
303351
if (allocated) {
304352
free(allocated);
305353
}
306354
} else {
307-
vsnprintf(buffer, remaining_space, fmtcpy, va);
355+
vsnprintf(buffer, remaining_space, fmtcpy, vacpy);
308356
}
309357

310358
PyObject* result = PyUnicode_FromString(full_buffer);
311359
free(full_buffer);
360+
va_end(vacpy);
312361
return result;
313362
}
314363

0 commit comments

Comments
 (0)