|
|
8631a2 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
8631a2 |
From: Peter Jones <pjones@redhat.com>
|
|
|
8631a2 |
Date: Fri, 19 Oct 2018 10:57:52 -0400
|
|
|
8631a2 |
Subject: [PATCH] Fix menu entry selection based on ID and title
|
|
|
8631a2 |
|
|
|
8631a2 |
Currently if grub_strtoul(saved_entry_value, NULL, 0) does not return an
|
|
|
8631a2 |
error, we assume the value it has produced is a correct index into our
|
|
|
8631a2 |
menu entry list, and do not try to interpret the value as the "id" or
|
|
|
8631a2 |
"title" . In cases where "id" or "title" start with a numeral, this
|
|
|
8631a2 |
makes them impossible to use as selection criteria.
|
|
|
8631a2 |
|
|
|
8631a2 |
This patch splits the search into three phases - matching id, matching
|
|
|
8631a2 |
title, and only once those have been exhausted, trying to interpret the
|
|
|
8631a2 |
ID as a numeral. In that case, we also require that the entire string
|
|
|
8631a2 |
is numeric, not merely a string with leading numeric characters.
|
|
|
8631a2 |
|
|
|
8631a2 |
Resolves: rhbz#1640979
|
|
|
8631a2 |
---
|
|
|
8631a2 |
grub-core/normal/menu.c | 146 +++++++++++++++++++++++++-----------------------
|
|
|
8631a2 |
1 file changed, 75 insertions(+), 71 deletions(-)
|
|
|
8631a2 |
|
|
|
8631a2 |
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
|
|
|
8631a2 |
index 6cb2a071490..95f7abaf2fd 100644
|
|
|
8631a2 |
--- a/grub-core/normal/menu.c
|
|
|
8631a2 |
+++ b/grub-core/normal/menu.c
|
|
|
8631a2 |
@@ -164,12 +164,12 @@ grub_menu_set_timeout (int timeout)
|
|
|
8631a2 |
}
|
|
|
8631a2 |
|
|
|
8631a2 |
static int
|
|
|
8631a2 |
-menuentry_eq (const char *id, const char *spec)
|
|
|
8631a2 |
+menuentry_eq (const char *id, const char *spec, int limit)
|
|
|
8631a2 |
{
|
|
|
8631a2 |
const char *ptr1, *ptr2;
|
|
|
8631a2 |
ptr1 = id;
|
|
|
8631a2 |
ptr2 = spec;
|
|
|
8631a2 |
- while (1)
|
|
|
8631a2 |
+ while (limit == -1 || ptr1 - id <= limit)
|
|
|
8631a2 |
{
|
|
|
8631a2 |
if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0)
|
|
|
8631a2 |
return ptr2 - spec;
|
|
|
8631a2 |
@@ -178,7 +178,11 @@ menuentry_eq (const char *id, const char *spec)
|
|
|
8631a2 |
if (*ptr2 == '>')
|
|
|
8631a2 |
ptr2++;
|
|
|
8631a2 |
if (*ptr1 != *ptr2)
|
|
|
8631a2 |
- return 0;
|
|
|
8631a2 |
+ {
|
|
|
8631a2 |
+ if (limit > -1 && ptr1 - id == limit && !*ptr1 && grub_isspace(*ptr2))
|
|
|
8631a2 |
+ return ptr1 -id -1;
|
|
|
8631a2 |
+ return 0;
|
|
|
8631a2 |
+ }
|
|
|
8631a2 |
if (*ptr1 == 0)
|
|
|
8631a2 |
return ptr1 - id;
|
|
|
8631a2 |
ptr1++;
|
|
|
8631a2 |
@@ -187,6 +191,61 @@ menuentry_eq (const char *id, const char *spec)
|
|
|
8631a2 |
return 0;
|
|
|
8631a2 |
}
|
|
|
8631a2 |
|
|
|
8631a2 |
+static int
|
|
|
8631a2 |
+get_entry_number_helper(grub_menu_t menu,
|
|
|
8631a2 |
+ const char * const val, const char ** const tail)
|
|
|
8631a2 |
+{
|
|
|
8631a2 |
+ /* See if the variable matches the title of a menu entry. */
|
|
|
8631a2 |
+ int entry = -1;
|
|
|
8631a2 |
+ grub_menu_entry_t e;
|
|
|
8631a2 |
+ int i;
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ for (i = 0, e = menu->entry_list; e; i++)
|
|
|
8631a2 |
+ {
|
|
|
8631a2 |
+ int l = 0;
|
|
|
8631a2 |
+ while (val[l] && !grub_isspace(val[l]))
|
|
|
8631a2 |
+ l++;
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ if (menuentry_eq (e->id, val, l))
|
|
|
8631a2 |
+ {
|
|
|
8631a2 |
+ if (tail)
|
|
|
8631a2 |
+ *tail = val + l;
|
|
|
8631a2 |
+ return i;
|
|
|
8631a2 |
+ }
|
|
|
8631a2 |
+ e = e->next;
|
|
|
8631a2 |
+ }
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ for (i = 0, e = menu->entry_list; e; i++)
|
|
|
8631a2 |
+ {
|
|
|
8631a2 |
+ int l = 0;
|
|
|
8631a2 |
+ while (val[l] && !grub_isspace(val[l]))
|
|
|
8631a2 |
+ l++;
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ if (menuentry_eq (e->title, val, l))
|
|
|
8631a2 |
+ {
|
|
|
8631a2 |
+ if (tail)
|
|
|
8631a2 |
+ *tail = val + l;
|
|
|
8631a2 |
+ return i;
|
|
|
8631a2 |
+ }
|
|
|
8631a2 |
+ e = e->next;
|
|
|
8631a2 |
+ }
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ if (tail)
|
|
|
8631a2 |
+ *tail = NULL;
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ entry = (int) grub_strtoul (val, tail, 0);
|
|
|
8631a2 |
+ if (grub_errno == GRUB_ERR_BAD_NUMBER ||
|
|
|
8631a2 |
+ (*tail && **tail && !grub_isspace(**tail)))
|
|
|
8631a2 |
+ {
|
|
|
8631a2 |
+ entry = -1;
|
|
|
8631a2 |
+ if (tail)
|
|
|
8631a2 |
+ *tail = NULL;
|
|
|
8631a2 |
+ grub_errno = GRUB_ERR_NONE;
|
|
|
8631a2 |
+ }
|
|
|
8631a2 |
+
|
|
|
8631a2 |
+ return entry;
|
|
|
8631a2 |
+}
|
|
|
8631a2 |
+
|
|
|
8631a2 |
/* Get the first entry number from the value of the environment variable NAME,
|
|
|
8631a2 |
which is a space-separated list of non-negative integers. The entry number
|
|
|
8631a2 |
which is returned is stripped from the value of NAME. If no entry number
|
|
|
8631a2 |
@@ -195,9 +254,8 @@ static int
|
|
|
8631a2 |
get_and_remove_first_entry_number (grub_menu_t menu, const char *name)
|
|
|
8631a2 |
{
|
|
|
8631a2 |
const char *val;
|
|
|
8631a2 |
- char *tail;
|
|
|
8631a2 |
+ const char *tail;
|
|
|
8631a2 |
int entry;
|
|
|
8631a2 |
- int sz = 0;
|
|
|
8631a2 |
|
|
|
8631a2 |
val = grub_env_get (name);
|
|
|
8631a2 |
if (! val)
|
|
|
8631a2 |
@@ -205,50 +263,24 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name)
|
|
|
8631a2 |
|
|
|
8631a2 |
grub_error_push ();
|
|
|
8631a2 |
|
|
|
8631a2 |
- entry = (int) grub_strtoul (val, &tail, 0);
|
|
|
8631a2 |
+ entry = get_entry_number_helper(menu, val, &tail);
|
|
|
8631a2 |
+ if (!(*tail == 0 || grub_isspace(*tail)))
|
|
|
8631a2 |
+ entry = -1;
|
|
|
8631a2 |
|
|
|
8631a2 |
- if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
|
|
8631a2 |
+ if (entry >= 0)
|
|
|
8631a2 |
{
|
|
|
8631a2 |
- /* See if the variable matches the title of a menu entry. */
|
|
|
8631a2 |
- grub_menu_entry_t e = menu->entry_list;
|
|
|
8631a2 |
- int i;
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- for (i = 0; e; i++)
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- sz = menuentry_eq (e->title, val);
|
|
|
8631a2 |
- if (sz < 1)
|
|
|
8631a2 |
- sz = menuentry_eq (e->id, val);
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (sz >= 1)
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- entry = i;
|
|
|
8631a2 |
- break;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
- e = e->next;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (sz > 0)
|
|
|
8631a2 |
- grub_errno = GRUB_ERR_NONE;
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (! e)
|
|
|
8631a2 |
- entry = -1;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (grub_errno == GRUB_ERR_NONE)
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- if (sz > 0)
|
|
|
8631a2 |
- tail += sz;
|
|
|
8631a2 |
-
|
|
|
8631a2 |
/* Skip whitespace to find the next entry. */
|
|
|
8631a2 |
while (*tail && grub_isspace (*tail))
|
|
|
8631a2 |
tail++;
|
|
|
8631a2 |
- grub_env_set (name, tail);
|
|
|
8631a2 |
+ if (*tail)
|
|
|
8631a2 |
+ grub_env_set (name, tail);
|
|
|
8631a2 |
+ else
|
|
|
8631a2 |
+ grub_env_unset (name);
|
|
|
8631a2 |
}
|
|
|
8631a2 |
else
|
|
|
8631a2 |
{
|
|
|
8631a2 |
grub_env_unset (name);
|
|
|
8631a2 |
grub_errno = GRUB_ERR_NONE;
|
|
|
8631a2 |
- entry = -1;
|
|
|
8631a2 |
}
|
|
|
8631a2 |
|
|
|
8631a2 |
grub_error_pop ();
|
|
|
8631a2 |
@@ -525,6 +557,7 @@ static int
|
|
|
8631a2 |
get_entry_number (grub_menu_t menu, const char *name)
|
|
|
8631a2 |
{
|
|
|
8631a2 |
const char *val;
|
|
|
8631a2 |
+ const char *tail;
|
|
|
8631a2 |
int entry;
|
|
|
8631a2 |
|
|
|
8631a2 |
val = grub_env_get (name);
|
|
|
8631a2 |
@@ -532,38 +565,9 @@ get_entry_number (grub_menu_t menu, const char *name)
|
|
|
8631a2 |
return -1;
|
|
|
8631a2 |
|
|
|
8631a2 |
grub_error_push ();
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- entry = (int) grub_strtoul (val, 0, 0);
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- /* See if the variable matches the title of a menu entry. */
|
|
|
8631a2 |
- grub_menu_entry_t e = menu->entry_list;
|
|
|
8631a2 |
- int i;
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- grub_errno = GRUB_ERR_NONE;
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- for (i = 0; e; i++)
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- if (menuentry_eq (e->title, val)
|
|
|
8631a2 |
- || menuentry_eq (e->id, val))
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- entry = i;
|
|
|
8631a2 |
- break;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
- e = e->next;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (! e)
|
|
|
8631a2 |
- entry = -1;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
-
|
|
|
8631a2 |
- if (grub_errno != GRUB_ERR_NONE)
|
|
|
8631a2 |
- {
|
|
|
8631a2 |
- grub_errno = GRUB_ERR_NONE;
|
|
|
8631a2 |
- entry = -1;
|
|
|
8631a2 |
- }
|
|
|
8631a2 |
-
|
|
|
8631a2 |
+ entry = get_entry_number_helper(menu, val, &tail);
|
|
|
8631a2 |
+ if (*tail != '\0')
|
|
|
8631a2 |
+ entry = -1;
|
|
|
8631a2 |
grub_error_pop ();
|
|
|
8631a2 |
|
|
|
8631a2 |
return entry;
|