I'm unsure whether an id starting with a numeral should be considered valid at all. Variable named 0x would be incorrect
Le lun. 22 avr. 2024, 17:57, Marek Marczykowski-Górecki < marma...@invisiblethingslab.com> a écrit : > From: Peter Jones <pjo...@redhat.com> > > Currently if grub_strtoul(saved_entry_value, NULL, 0) does not return an > error, we assume the value it has produced is a correct index into our > menu entry list, and do not try to interpret the value as the "id" or > "title" . In cases where "id" or "title" start with a numeral, this > makes them impossible to use as selection criteria. > > This patch splits the search into three phases - matching id, matching > title, and only once those have been exhausted, trying to interpret the > ID as a numeral. In that case, we also require that the entire string > is numeric, not merely a string with leading numeric characters. > > Resolves: rhbz#1640979 > > Signed-off-by: Peter Jones <pjo...@redhat.com> > [javierm: fix menu entry selection based on title] > Signed-off-by: Javier Martinez Canillas <javi...@redhat.com> > --- > grub-core/normal/menu.c | 141 ++++++++++++++++++++--------------------- > 1 file changed, 71 insertions(+), 70 deletions(-) > > diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c > index 6444ee6..b0cfa32 100644 > --- a/grub-core/normal/menu.c > +++ b/grub-core/normal/menu.c > @@ -164,12 +164,12 @@ grub_menu_set_timeout (int timeout) > } > > static int > -menuentry_eq (const char *id, const char *spec) > +menuentry_eq (const char *id, const char *spec, int limit) > { > const char *ptr1, *ptr2; > ptr1 = id; > ptr2 = spec; > - while (1) > + while (limit == -1 || ptr1 - id <= limit) > { > if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) > return ptr2 - spec; > @@ -178,7 +178,11 @@ menuentry_eq (const char *id, const char *spec) > if (*ptr2 == '>') > ptr2++; > if (*ptr1 != *ptr2) > - return 0; > + { > + if (limit > -1 && ptr1 - id == limit && !*ptr1 && > grub_isspace(*ptr2)) > + return ptr1 -id -1; > + return 0; > + } > if (*ptr1 == 0) > return ptr1 - id; > ptr1++; > @@ -187,6 +191,58 @@ menuentry_eq (const char *id, const char *spec) > return 0; > } > > +static int > +get_entry_number_helper(grub_menu_t menu, > + const char * const val, const char ** const tail) > +{ > + /* See if the variable matches the title of a menu entry. */ > + int entry = -1; > + grub_menu_entry_t e; > + int i; > + > + for (i = 0, e = menu->entry_list; e; i++) > + { > + int l = 0; > + while (val[l] && !grub_isspace(val[l])) > + l++; > + > + if (menuentry_eq (e->id, val, l)) > + { > + if (tail) > + *tail = val + l; > + return i; > + } > + e = e->next; > + } > + > + for (i = 0, e = menu->entry_list; e; i++) > + { > + > + if (menuentry_eq (e->title, val, -1)) > + { > + if (tail) > + *tail = NULL; > + return i; > + } > + e = e->next; > + } > + > + if (tail) > + *tail = NULL; > + > + entry = (int) grub_strtoul (val, tail, 0); > + if (grub_errno == GRUB_ERR_BAD_NUMBER || > + (*tail && **tail && !grub_isspace(**tail))) > + { > + entry = -1; > + if (tail) > + *tail = NULL; > + grub_errno = GRUB_ERR_NONE; > + } > + > + return entry; > +} > + > /* Get the first entry number from the value of the environment variable > NAME, > which is a space-separated list of non-negative integers. The entry > number > which is returned is stripped from the value of NAME. If no entry > number > @@ -196,7 +252,6 @@ get_and_remove_first_entry_number (grub_menu_t menu, > const char *name) > { > const char *val, *tail; > int entry; > - int sz = 0; > > val = grub_env_get (name); > if (! val) > @@ -204,50 +259,24 @@ get_and_remove_first_entry_number (grub_menu_t menu, > const char *name) > > grub_error_push (); > > - entry = (int) grub_strtoul (val, &tail, 0); > - > - if (grub_errno == GRUB_ERR_BAD_NUMBER) > - { > - /* See if the variable matches the title of a menu entry. */ > - grub_menu_entry_t e = menu->entry_list; > - int i; > - > - for (i = 0; e; i++) > - { > - sz = menuentry_eq (e->title, val); > - if (sz < 1) > - sz = menuentry_eq (e->id, val); > - > - if (sz >= 1) > - { > - entry = i; > - break; > - } > - e = e->next; > - } > + entry = get_entry_number_helper(menu, val, &tail); > + if (!(*tail == 0 || grub_isspace(*tail))) > + entry = -1; > > - if (sz > 0) > - grub_errno = GRUB_ERR_NONE; > - > - if (! e) > - entry = -1; > - } > - > - if (grub_errno == GRUB_ERR_NONE) > + if (entry >= 0) > { > - if (sz > 0) > - tail += sz; > - > /* Skip whitespace to find the next entry. */ > while (*tail && grub_isspace (*tail)) > tail++; > - grub_env_set (name, tail); > + if (*tail) > + grub_env_set (name, tail); > + else > + grub_env_unset (name); > } > else > { > grub_env_unset (name); > grub_errno = GRUB_ERR_NONE; > - entry = -1; > } > > grub_error_pop (); > @@ -524,6 +553,7 @@ static int > get_entry_number (grub_menu_t menu, const char *name) > { > const char *val; > + const char *tail; > int entry; > > val = grub_env_get (name); > @@ -531,38 +561,9 @@ get_entry_number (grub_menu_t menu, const char *name) > return -1; > > grub_error_push (); > - > - entry = (int) grub_strtoul (val, 0, 0); > - > - if (grub_errno == GRUB_ERR_BAD_NUMBER) > - { > - /* See if the variable matches the title of a menu entry. */ > - grub_menu_entry_t e = menu->entry_list; > - int i; > - > - grub_errno = GRUB_ERR_NONE; > - > - for (i = 0; e; i++) > - { > - if (menuentry_eq (e->title, val) > - || menuentry_eq (e->id, val)) > - { > - entry = i; > - break; > - } > - e = e->next; > - } > - > - if (! e) > - entry = -1; > - } > - > - if (grub_errno != GRUB_ERR_NONE) > - { > - grub_errno = GRUB_ERR_NONE; > - entry = -1; > - } > - > + entry = get_entry_number_helper(menu, val, &tail); > + if (tail && *tail != '\0') > + entry = -1; > grub_error_pop (); > > return entry; > -- > git-series 0.9.1 > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel >
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel