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

Reply via email to