Skip to content

Commit dcddaae

Browse files
committed
Fix va_list reuse with va_copy in boot_sprintf and nanoprintf
1 parent 16a9dae commit dcddaae

2 files changed

Lines changed: 34 additions & 12 deletions

File tree

src/ce/boot_printf.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
#include <stddef.h>
22
#include <stdarg.h>
3-
#include <string.h>
43
#include <stdio.h>
5-
#include <stdbool.h>
64
#include <stdlib.h>
75
#include <ti/sprintf.h>
86

97
#define SINK (char *__restrict)0xE40000
108

119
int boot_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list args) {
12-
int str_len = boot_vsprintf(SINK, format, args);
10+
va_list args_copy;
11+
va_copy(args_copy, args);
12+
int str_len = boot_vsprintf(SINK, format, args_copy);
13+
va_end(args_copy);
14+
1315
if (buffer == NULL || count == 0) {
1416
return str_len;
1517
}
16-
if ((size_t)str_len >= count || str_len <= 0) {
17-
// won't fit or invalid formatting
18+
// str_len == 0 can take this fast path
19+
if ((size_t)str_len >= count || str_len < 0 || str_len == 0) {
20+
// won't fit, invalid formatting, or empty string
1821
*buffer = '\0';
1922
return str_len;
2023
}
@@ -32,18 +35,30 @@ int boot_snprintf(char *__restrict buffer, size_t count, const char *__restrict
3235
__attribute__((weak, alias("boot_snprintf"))) int snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...);
3336

3437
int boot_vasprintf(char **__restrict p_buffer, const char *__restrict format, va_list args) {
35-
int ret = -1;
3638
*p_buffer = NULL;
37-
int str_len = boot_vsprintf(SINK, format, args);
39+
va_list args_copy;
40+
va_copy(args_copy, args);
41+
int str_len = boot_vsprintf(SINK, format, args_copy);
42+
va_end(args_copy);
43+
3844
if (str_len < 0) {
3945
// formatting error
4046
return str_len;
4147
}
4248
size_t buffer_size = (size_t)str_len + 1;
43-
*p_buffer = malloc(buffer_size);
44-
if (*p_buffer != NULL) {
45-
ret = boot_vsprintf(*p_buffer, format, args);
49+
char* buffer = malloc(buffer_size);
50+
if (buffer == NULL) {
51+
// malloc failure
52+
return -1;
53+
}
54+
va_copy(args_copy, args);
55+
int ret = boot_vsprintf(buffer, format, args_copy);
56+
va_end(args_copy);
57+
if (ret < 0) {
58+
free(buffer);
59+
return ret;
4660
}
61+
*p_buffer = buffer;
4762
return ret;
4863
}
4964
__attribute__((weak, alias("boot_vasprintf"))) int vasprintf(char **__restrict p_buffer, const char *__restrict format, va_list args);

src/libc/printf/nanoprintf.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,13 @@ int sprintf(char *__restrict buffer, const char *__restrict format, ...)
9393

9494
int vasprintf(char **__restrict p_str, const char *__restrict format, va_list vlist) {
9595
*p_str = NULL;
96-
int str_len = vsnprintf(NULL, 0, format, vlist);
96+
va_list vlist_copy;
97+
va_copy(vlist_copy, vlist);
98+
int str_len = vsnprintf(NULL, 0, format, vlist_copy);
99+
va_end(vlist_copy);
100+
97101
if (str_len < 0) {
102+
// formatting error
98103
return str_len;
99104
}
100105
size_t buf_len = (size_t)str_len + 1;
@@ -103,7 +108,9 @@ int vasprintf(char **__restrict p_str, const char *__restrict format, va_list vl
103108
// malloc failure
104109
return -1;
105110
}
106-
int ret = vsnprintf(buf, buf_len, format, vlist);
111+
va_copy(vlist_copy, vlist);
112+
int ret = vsnprintf(buf, buf_len, format, vlist_copy);
113+
va_end(vlist_copy);
107114
if (ret < 0) {
108115
free(buf);
109116
return ret;

0 commit comments

Comments
 (0)