Skip to content

Commit 24ba959

Browse files
committed
[kernel] fix vsnprintf
1 parent da5098b commit 24ba959

3 files changed

Lines changed: 35 additions & 18 deletions

File tree

‎src/klibc/rt_vsnprintf_std.c‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,9 @@ static inline output_gadget_t buffer_gadget(char* buffer, size_t buffer_size)
371371
static inline printf_size_t strnlen_s_(const char* str, printf_size_t maxsize)
372372
{
373373
const char* s;
374-
for (s = str; *s && maxsize--; ++s);
374+
// check the bound before dereferencing,
375+
// so that at most maxsize characters are read.
376+
for (s = str; maxsize && *s; ++s, --maxsize);
375377
return (printf_size_t)(s - str);
376378
}
377379

@@ -1053,7 +1055,12 @@ static inline void format_string_loop(output_gadget_t* output, const char* forma
10531055
}
10541056
else if (*format == '*') {
10551057
const int precision_ = va_arg(args, int);
1056-
precision = precision_ > 0 ? (printf_size_t) precision_ : 0U;
1058+
if (precision_ < 0) {
1059+
flags &= ~FLAGS_PRECISION;
1060+
}
1061+
else {
1062+
precision = (printf_size_t) precision_;
1063+
}
10571064
ADVANCE_IN_FORMAT_STRING(format);
10581065
}
10591066
}

‎src/klibc/rt_vsnprintf_tiny.c‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ static char *print_number(char *buf,
8383
static const char large_digits[] = "0123456789ABCDEF";
8484
int i = 0;
8585
int size = 0;
86+
int is_zero = 0;
8687

8788
size = s;
8889

@@ -151,6 +152,7 @@ static char *print_number(char *buf,
151152
}
152153

153154
i = 0;
155+
is_zero = (num == 0);
154156
if (num == 0)
155157
{
156158
tmp[i++] = '0';
@@ -253,7 +255,7 @@ static char *print_number(char *buf,
253255
}
254256

255257
/* put number in the temporary buffer */
256-
while (i-- > 0 && (precision_bak != 0))
258+
while (i-- > 0 && !((precision_bak == 0) && is_zero))
257259
{
258260
if (buf < end)
259261
{
@@ -382,8 +384,12 @@ int rt_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
382384
++fmt;
383385
/* it's the next argument */
384386
precision = va_arg(args, int);
387+
if (precision < 0)
388+
{
389+
precision = -1;
390+
}
385391
}
386-
if (precision < 0)
392+
else
387393
{
388394
precision = 0;
389395
}
@@ -451,12 +457,7 @@ int rt_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
451457
s = "(null)";
452458
}
453459

454-
for (len = 0; (len != field_width) && (s[len] != '\0'); len++);
455-
456-
if (precision > 0 && len > precision)
457-
{
458-
len = precision;
459-
}
460+
for (len = 0; (precision < 0 || len < precision) && (s[len] != '\0'); len++);
460461

461462
if (!(flags & LEFT))
462463
{

‎src/klibc/utest/TC_rt_sprintf.c‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,7 @@ SPRINTF_TEST_CASE(specifier)
334334
SPRINTF_TEST_CASE(width)
335335
{
336336
char buffer[base_buffer_size];
337-
#ifdef RT_KLIBC_USING_VSNPRINTF_STANDARD
338337
SPRINTF_CHECK("Hello testing", buffer, "%1s", "Hello testing");
339-
#endif /* RT_KLIBC_USING_VSNPRINTF_STANDARD */
340338
SPRINTF_CHECK("1024", buffer, "%1d", 1024);
341339
SPRINTF_CHECK("-1024", buffer, "%1d", -1024);
342340
SPRINTF_CHECK("1024", buffer, "%1i", 1024);
@@ -837,10 +835,6 @@ SPRINTF_TEST_CASE(tiny_floating_point_values)
837835
SPRINTF_TEST_CASE(length)
838836
{
839837
char buffer[base_buffer_size];
840-
SPRINTF_CHECK("", buffer, "%.0s", "Hello testing");
841-
SPRINTF_CHECK(" ", buffer, "%20.0s", "Hello testing");
842-
SPRINTF_CHECK("", buffer, "%.s", "Hello testing");
843-
SPRINTF_CHECK(" ", buffer, "%20.s", "Hello testing");
844838
SPRINTF_CHECK(" 1024", buffer, "%20.0d", 1024);
845839
SPRINTF_CHECK(" -1024", buffer, "%20.0d", -1024);
846840
SPRINTF_CHECK(" ", buffer, "%20.d", 0);
@@ -972,6 +966,19 @@ SPRINTF_TEST_CASE(pointer)
972966
SPRINTF_TEST_CASE(string_length)
973967
{
974968
char buffer[base_buffer_size];
969+
#if !defined(RT_KLIBC_USING_LIBC_VSNPRINTF)
970+
char unterminated[] = {'A', 'B', 'C'};
971+
#endif
972+
973+
SPRINTF_CHECK("", buffer, "%.0s", "Hello testing");
974+
SPRINTF_CHECK(" ", buffer, "%20.0s", "Hello testing");
975+
SPRINTF_CHECK("", buffer, "%.s", "Hello testing");
976+
SPRINTF_CHECK(" ", buffer, "%20.s", "Hello testing");
977+
SPRINTF_CHECK("", buffer, "%.*s", 0, "Hello testing");
978+
#if !defined(RT_KLIBC_USING_LIBC_VSNPRINTF)
979+
SPRINTF_CHECK("Hello testing", buffer, "%.*s", -1, "Hello testing");
980+
SPRINTF_CHECK("ABC", buffer, "%.3s", unterminated);
981+
#endif
975982
SPRINTF_CHECK("This", buffer, "%.4s", "This is a test");
976983
SPRINTF_CHECK("test", buffer, "%.4s", "test");
977984
SPRINTF_CHECK("123", buffer, "%.7s", "123");
@@ -989,14 +996,16 @@ SPRINTF_TEST_CASE(misc)
989996
{
990997
char buffer[base_buffer_size];
991998
SPRINTF_CHECK("53000atest-20 bit", buffer, "%u%u%ctest%d %s", 5, 3000, 'a', -20, "bit");
992-
#ifdef RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
993-
SPRINTF_CHECK("0.33", buffer, "%.*f", 2, 0.33333333);
994999
SPRINTF_CHECK("1", buffer, "%.*d", -1, 1);
9951000
SPRINTF_CHECK("foo", buffer, "%.3s", "foobar");
9961001
SPRINTF_CHECK(" ", buffer, "% .0d", 0);
1002+
SPRINTF_CHECK("5", buffer, "%.0d", 5);
1003+
SPRINTF_CHECK("", buffer, "%.0d", 0);
9971004
SPRINTF_CHECK(" 00004", buffer, "%10.5d", 4);
9981005
SPRINTF_CHECK("hi x", buffer, "%*sx", -3, "hi");
9991006
SPRINTF_CHECK("00123 ", buffer, "%-20.5i", 123);
1007+
#ifdef RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
1008+
SPRINTF_CHECK("0.33", buffer, "%.*f", 2, 0.33333333);
10001009
SPRINTF_CHECK("-67224.546875000000000000", buffer, "%.18f", -67224.546875);
10011010
#endif /* RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS */
10021011
#ifdef RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS

0 commit comments

Comments
 (0)