glibc 2.43 enabled 2MB Transparent Huge Pages (THP) by default on arm64:
https://sourceware.org/git/?p=glibc.git;a=commit;h=321e1fc73f53081d92ba357cdd48c56b79292020

This causes malloc() to set errno to ENOENT in some cases on arm64,
even with successful allocations. busybox printf uses errno as an
accumulator and returns exit code 1 if errno is non-zero. Since glibc
2.43 unexpectedly sets errno during successful printf() calls, busybox
printf returns exit code 1 even when output is correct:

  FAIL: printf understands %s '"x' "'y" "'zTAIL"  (exit 1, expected 0)
  FAIL: printf handles positive numbers for %f      (exit 1, expected 0)

Note: the printf output itself is correct in both cases — only the
exit code is wrong.

Fix by saving and restoring errno around each printf() call in
coreutils/printf.c, only preserving a non-zero errno if an actual
error occurred (ret < 0).

This fix was originally proposed by Aurelien Jarno in Debian bug #1128825:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1128825
Patch link: https://bugs.debian.org/cgi-bin/bugreport.cgi?att=1;bug=1128825;filename=busybox_glibc-2.43_thp.patch;msg=10

Patch:

diff --git a/coreutils/printf.c b/coreutils/printf.c index 3cd48cfcc..a5d995ab5 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -191,6 +191,7 @@ static void print_direc(char *format, unsigned fmt_length, double dv; char saved; char *have_prec, *have_width; + int saved_errno, ret; saved = format[fmt_length]; format[fmt_length] = '\0'; @@ -205,22 +206,32 @@ static void print_direc(char *format, unsigned fmt_length, switch (format[fmt_length - 1]) { case 'c': - printf(format, *argument); + saved_errno = errno; + ret = printf(format, *argument); + /* Restore errno if there was no error */ + if (ret >= 0) { + errno = saved_errno; + } break; case 'd': case 'i': llv = my_xstrtoll(skip_whitespace(argument));  print_long: + saved_errno = errno; if (!have_width) { if (!have_prec) - printf(format, llv); + ret = printf(format, llv); else - printf(format, precision, llv); + ret = printf(format, precision, llv); } else { if (!have_prec) - printf(format, field_width, llv); + ret = printf(format, field_width, llv); else - printf(format, field_width, precision, llv); + ret = printf(format, field_width, precision, llv); + } + /* Restore errno if there was no error */ + if (ret >= 0) { + errno = saved_errno; } break; case 'o': @@ -238,16 +249,21 @@ static void print_direc(char *format, unsigned fmt_length, } else { /* Hope compiler will optimize it out by moving call * instruction after the ifs... */ + saved_errno = errno; if (!have_width) { if (!have_prec) - printf(format, argument, /*unused:*/ argument, argument); + ret = printf(format, argument, /*unused:*/ argument, argument); else - printf(format, precision, argument, /*unused:*/ argument); + ret = printf(format, precision, argument, /*unused:*/ argument); } else { if (!have_prec) - printf(format, field_width, argument, /*unused:*/ argument); + ret = printf(format, field_width, argument, /*unused:*/ argument); else - printf(format, field_width, precision, argument); + ret = printf(format, field_width, precision, argument); + } + /* Restore errno if there was no error */ + if (ret >= 0) { + errno = saved_errno; } break; } @@ -257,16 +273,21 @@ static void print_direc(char *format, unsigned fmt_length, case 'g': case 'G': dv = my_xstrtod(argument); + saved_errno = errno; if (!have_width) { if (!have_prec) - printf(format, dv); + ret = printf(format, dv); else - printf(format, precision, dv); + ret = printf(format, precision, dv); } else { if (!have_prec) - printf(format, field_width, dv); + ret = printf(format, field_width, dv); else - printf(format, field_width, precision, dv); + ret = printf(format, field_width, precision, dv); + } + /* Restore errno if there was no error */ + if (ret >= 0) { + errno = saved_errno; } break; } /* switch */

Signed-off-by: Aurelien Jarno <[email protected]>
Signed-off-by: Hemanth Kumar M D <[email protected]>

--
Regards,
Hemanth Kumar M D
_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox

Reply via email to