Hello dear GRUB developers, I recently came across a strange behavior of GRUB2:
Calling grub_printf with an 80 character string (grub_printf(str) == 80) 80 times in a row leads to grub being unresponsive and de facto being trapped in endless loop (of printing newlines?).
This behavior does not occur before switching to normal mode, when grub_printf still calls grub_xputs_dumb. It only occurs after switching to normal mode, when grub_printf calls grub_xputs_normal.
The bug is not triggered, if 80*80 (or more) characters are being printed at once by grub_printf: A string of at least 80 characters has to be grub_printf'd at least 80 times in a row.
I attached a small patch to demonstrate the bug: - printf_test prints an 80-char long string 80 times successively- this test succeeds with grub_printf using grub_xputs_dumb (before normal mode) - this test fails with grub_printf using grub_xputs_normal (after switching to normal mode)
I could reproduce this behavior within qemu and on several different physical systems. For testing, I used the current master-branch and grub-2.02-rc2 (8014b7b), but prior versions are affected too probably.
Best regards, Stephan
From 8a21e144819113ca222090a08dc4e04a8faad58b Mon Sep 17 00:00:00 2001 From: root <root@localhost> Date: Fri, 19 Jul 2019 09:30:39 +0000 Subject: [PATCH 1/1] Bug in grub_xputs_normal --- grub-core/normal/main.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index 1b03dfd57..0442c9cd7 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -33,6 +33,34 @@ #include <grub/charset.h> #include <grub/script_sh.h> #include <grub/bufio.h> +#include <grub/time.h> + +/* FIXME + * + * printf_test succeeds with grub_printf using grub_xputs_dumb (before normal + * mode), but fails with grub_printf using grub_xputs_normal (after switching + * to normal mode). + * + * the buggy behavior occurs when + * - grub_strlen(buffer) >= 80, AND + * - buffer printed 80 times successively + */ + +static void +printf_test(const char print_char) +{ + char buffer[80+1]; + unsigned int idx; + unsigned int print_counter; + + /* fill buffer with print_char */ + for (idx = 0; idx < sizeof(buffer) - 1; idx++) + buffer[idx] = print_char; + buffer[idx] = '\0'; + + for (print_counter = 80; print_counter > 0; print_counter--) + grub_printf("%s", buffer); +} GRUB_MOD_LICENSE ("GPLv3+"); @@ -506,8 +534,10 @@ GRUB_MOD_INIT(normal) grub_script_init (); grub_menu_init (); + printf_test('0'); grub_xputs_saved = grub_xputs; grub_xputs = grub_xputs_normal; + printf_test('1'); /* Normal mode shouldn't be unloaded. */ if (mod) -- 2.11.0
_______________________________________________ Bug-grub mailing list Bug-grub@gnu.org https://lists.gnu.org/mailman/listinfo/bug-grub