]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
misc: Make grub_strtol() "end" pointers have safer const qualifiers
authorPeter Jones <pjones@redhat.com>
Fri, 21 Feb 2020 21:39:33 +0000 (16:39 -0500)
committerDaniel Kiper <daniel.kiper@oracle.com>
Fri, 28 Feb 2020 11:41:29 +0000 (12:41 +0100)
Currently the string functions grub_strtol(), grub_strtoul(), and
grub_strtoull() don't declare the "end" pointer in such a way as to
require the pointer itself or the character array to be immutable to the
implementation, nor does the C standard do so in its similar functions,
though it does require us not to change any of it.

The typical declarations of these functions follow this pattern:

long
strtol(const char * restrict nptr, char ** restrict endptr, int base);

Much of the reason for this is historic, and a discussion of that
follows below, after the explanation of this change.  (GRUB currently
does not include the "restrict" qualifiers, and we name the arguments a
bit differently.)

The implementation is semantically required to treat the character array
as immutable, but such accidental modifications aren't stopped by the
compiler, and the semantics for both the callers and the implementation
of these functions are sometimes also helped by adding that requirement.

This patch changes these declarations to follow this pattern instead:

long
strtol(const char * restrict nptr,
       const char ** const restrict endptr,
       int base);

This means that if any modification to these functions accidentally
introduces either an errant modification to the underlying character
array, or an accidental assignment to endptr rather than *endptr, the
compiler should generate an error.  (The two uses of "restrict" in this
case basically mean strtol() isn't allowed to modify the character array
by going through *endptr, and endptr isn't allowed to point inside the
array.)

It also means the typical use case changes to:

  char *s = ...;
  const char *end;
  long l;

  l = strtol(s, &end, 10);

Or even:

  const char *p = str;
  while (p && *p) {
  long l = strtol(p, &p, 10);
  ...
  }

This fixes 26 places where we discard our attempts at treating the data
safely by doing:

  const char *p = str;
  long l;

  l = strtol(p, (char **)&ptr, 10);

It also adds 5 places where we do:

  char *p = str;
  while (p && *p) {
  long l = strtol(p, (const char ** const)&p, 10);
  ...
  /* more calls that need p not to be pointer-to-const */
  }

While moderately distasteful, this is a better problem to have.

With one minor exception, I have tested that all of this compiles
without relevant warnings or errors, and that /much/ of it behaves
correctly, with gcc 9 using 'gcc -W -Wall -Wextra'.  The one exception
is the changes in grub-core/osdep/aros/hostdisk.c , which I have no idea
how to build.

Because the C standard defined type-qualifiers in a way that can be
confusing, in the past there's been a slow but fairly regular stream of
churn within our patches, which add and remove the const qualifier in many
of the users of these functions.  This change should help avoid that in
the future, and in order to help ensure this, I've added an explanation
in misc.h so that when someone does get a compiler warning about a type
error, they have the fix at hand.

The reason we don't have "const" in these calls in the standard is
purely anachronistic: C78 (de facto) did not have type qualifiers in the
syntax, and the "const" type qualifier was added for C89 (I think; it
may have been later).  strtol() appears to date from 4.3BSD in 1986,
which means it could not be added to those functions in the standard
without breaking compatibility, which is usually avoided.

The syntax chosen for type qualifiers is what has led to the churn
regarding usage of const, and is especially confusing on string
functions due to the lack of a string type.  Quoting from C99, the
syntax is:

 declarator:
  pointer[opt] direct-declarator
 direct-declarator:
  identifier
  ( declarator )
  direct-declarator [ type-qualifier-list[opt] assignment-expression[opt] ]
  ...
  direct-declarator [ type-qualifier-list[opt] * ]
  ...
 pointer:
  * type-qualifier-list[opt]
  * type-qualifier-list[opt] pointer
 type-qualifier-list:
  type-qualifier
  type-qualifier-list type-qualifier
 ...
 type-qualifier:
  const
  restrict
  volatile

So the examples go like:

const char foo; // immutable object
const char *foo; // mutable pointer to object
char * const foo; // immutable pointer to mutable object
const char * const foo; // immutable pointer to immutable object
const char const * const foo;  // XXX extra const keyword in the middle
const char * const * const foo; // immutable pointer to immutable
//   pointer to immutable object
const char ** const foo; // immutable pointer to mutable pointer
//   to immutable object

Making const left-associative for * and right-associative for everything
else may not have been the best choice ever, but here we are, and the
inevitable result is people using trying to use const (as they should!),
putting it at the wrong place, fighting with the compiler for a bit, and
then either removing it or typecasting something in a bad way.  I won't
go into describing restrict, but its syntax has exactly the same issue
as with const.

Anyway, the last example above actually represents the *behavior* that's
required of strtol()-like functions, so that's our choice for the "end"
pointer.

Signed-off-by: Peter Jones <pjones@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
39 files changed:
grub-core/commands/date.c
grub-core/commands/i386/cmostest.c
grub-core/commands/i386/pc/play.c
grub-core/commands/i386/rdmsr.c
grub-core/commands/i386/wrmsr.c
grub-core/commands/password_pbkdf2.c
grub-core/commands/pcidump.c
grub-core/commands/regexp.c
grub-core/commands/setpci.c
grub-core/commands/test.c
grub-core/commands/videoinfo.c
grub-core/disk/diskfilter.c
grub-core/disk/lvm.c
grub-core/efiemu/pnvram.c
grub-core/gfxmenu/gui_circular_progress.c
grub-core/gfxmenu/theme_loader.c
grub-core/kern/fs.c
grub-core/kern/misc.c
grub-core/kern/partition.c
grub-core/lib/arg.c
grub-core/lib/json/json.c
grub-core/lib/legacy_parse.c
grub-core/lib/syslinux_parse.c
grub-core/loader/i386/bsd.c
grub-core/loader/i386/linux.c
grub-core/loader/i386/pc/linux.c
grub-core/loader/i386/xen_fileXX.c
grub-core/mmap/mmap.c
grub-core/net/http.c
grub-core/net/net.c
grub-core/normal/menu.c
grub-core/osdep/aros/hostdisk.c
grub-core/osdep/devmapper/hostdisk.c
grub-core/script/execute.c
grub-core/term/serial.c
grub-core/term/terminfo.c
grub-core/tests/strtoull_test.c
include/grub/misc.h
util/grub-fstest.c

index 8e1f41f141bf203a801986442db2dcec6104fa7e..5cb4fafd454cdceb7b3a0b5d86cc2fda41c99369 100644 (file)
@@ -59,7 +59,8 @@ grub_cmd_date (grub_command_t cmd __attribute__ ((unused)),
 
   for (; argc; argc--, args++)
     {
-      char *p, c;
+      const char *p;
+      char c;
       int m1, ofs, n, cur_mask;
 
       p = args[0];
index c839b704dc50c74f5249e6521bd64585e00ec09e..9f6b56a2f0c9babb7b914859553bae8212fab1a8 100644 (file)
@@ -27,7 +27,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 static grub_err_t
 parse_args (int argc, char *argv[], int *byte, int *bit)
 {
-  char *rest;
+  const char *rest;
 
   if (argc != 1)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "address required");
index c8181310515b5bdc9ea822657d408956c1ce1e1f..a980e46883c36da0fd173fe28d0a619d0dee6720 100644 (file)
@@ -132,7 +132,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
     }
   else
     {
-      char *end;
+      const char *end;
       unsigned tempo;
       struct note note;
       int i;
index 15b9adfca6759b41d55d04dbc9a766daafb2d754..46c4346da1b66626e27c6271423bd23d55444c8f 100644 (file)
@@ -44,7 +44,7 @@ grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv)
 {
   grub_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr;
   grub_uint64_t value;
-  char *ptr;
+  const char *ptr;
   char buf[sizeof("1122334455667788")];
 
   /*
index 9c5e510eb4402ff2a869b2b780861ccde118d30c..fa76f5aed1174bc2cef39e9404a5bdf994645de2 100644 (file)
@@ -37,7 +37,7 @@ grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char
 {
   grub_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr;
   grub_uint64_t value;
-  char *ptr;
+  const char *ptr;
 
   /*
    * The CPUID instruction should be used to determine whether MSRs
index da636e6217a893eb18a198ba87a6dcab47409660..ab845d25eb3d477e4524de1e43d0f20d04ea063f 100644 (file)
@@ -86,7 +86,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
                   int argc, char **args)
 {
   grub_err_t err;
-  char *ptr, *ptr2;
+  const char *ptr, *ptr2;
   grub_uint8_t *ptro;
   struct pbkdf2_password *pass;
 
index f99ad4a216f485c99778277a8c83747d28c9682f..f72628fce2d9bc7c76677441f84712c845f68592 100644 (file)
@@ -95,7 +95,7 @@ grub_cmd_pcidump (grub_extcmd_context_t ctxt,
   if (ctxt->state[0].set)
     {
       ptr = ctxt->state[0].arg;
-      ctx.pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
+      ctx.pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff);
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -108,8 +108,7 @@ grub_cmd_pcidump (grub_extcmd_context_t ctxt,
       if (*ptr != ':')
        return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':');
       ptr++;
-      ctx.pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff)
-       << 16;
+      ctx.pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff) << 16;
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        grub_errno = GRUB_ERR_NONE;
       else
@@ -121,10 +120,10 @@ grub_cmd_pcidump (grub_extcmd_context_t ctxt,
   if (ctxt->state[1].set)
     {
       const char *optr;
-      
+
       ptr = ctxt->state[1].arg;
       optr = ptr;
-      ctx.bus = grub_strtoul (ptr, (char **) &ptr, 16);
+      ctx.bus = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -138,7 +137,7 @@ grub_cmd_pcidump (grub_extcmd_context_t ctxt,
        return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':');
       ptr++;
       optr = ptr;
-      ctx.device = grub_strtoul (ptr, (char **) &ptr, 16);
+      ctx.device = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -149,7 +148,7 @@ grub_cmd_pcidump (grub_extcmd_context_t ctxt,
       if (*ptr == '.')
        {
          ptr++;
-         ctx.function = grub_strtoul (ptr, (char **) &ptr, 16);
+         ctx.function = grub_strtoul (ptr, &ptr, 16);
          if (grub_errno)
            return grub_errno;
          ctx.check_function = 1;
index f00b184c81e4ac9730e01671d42ab17a6a404002..7c5c72fe46013055e9d3fb3123060452e9881078 100644 (file)
@@ -64,7 +64,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches,
 {
   int i;
   char *p;
-  char *q;
+  const char * q;
   grub_err_t err;
   unsigned long j;
 
index d5bc97d60b29dc1b9186f3c1de361e0fa8eb971c..e966af080a6fb93077c50239e7ded897207dfe2d 100644 (file)
@@ -169,7 +169,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
   if (ctxt->state[0].set)
     {
       ptr = ctxt->state[0].arg;
-      pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
+      pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff);
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -182,8 +182,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
       if (*ptr != ':')
        return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':');
       ptr++;
-      pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff)
-       << 16;
+      pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff) << 16;
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        grub_errno = GRUB_ERR_NONE;
       else
@@ -197,10 +196,10 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
   if (ctxt->state[1].set)
     {
       const char *optr;
-      
+
       ptr = ctxt->state[1].arg;
       optr = ptr;
-      bus = grub_strtoul (ptr, (char **) &ptr, 16);
+      bus = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -214,7 +213,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
        return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':');
       ptr++;
       optr = ptr;
-      device = grub_strtoul (ptr, (char **) &ptr, 16);
+      device = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno == GRUB_ERR_BAD_NUMBER)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -225,7 +224,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
       if (*ptr == '.')
        {
          ptr++;
-         function = grub_strtoul (ptr, (char **) &ptr, 16);
+         function = grub_strtoul (ptr, &ptr, 16);
          if (grub_errno)
            return grub_errno;
          check_function = 1;
@@ -253,7 +252,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
   if (i == ARRAY_SIZE (pci_registers))
     {
       regsize = 0;
-      regaddr = grub_strtoul (ptr, (char **) &ptr, 16);
+      regaddr = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno)
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown register");
     }
@@ -270,7 +269,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
   if (*ptr == '+')
     {
       ptr++;
-      regaddr += grub_strtoul (ptr, (char **) &ptr, 16);
+      regaddr += grub_strtoul (ptr, &ptr, 16);
       if (grub_errno)
        return grub_errno;
     }
@@ -302,14 +301,14 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
   if (*ptr == '=')
     {
       ptr++;
-      regwrite = grub_strtoul (ptr, (char **) &ptr, 16);
+      regwrite = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno)
        return grub_errno;
       write_mask = 0xffffffff;
       if (*ptr == ':')
        {
          ptr++;
-         write_mask = grub_strtoul (ptr, (char **) &ptr, 16);
+         write_mask = grub_strtoul (ptr, &ptr, 16);
          if (grub_errno)
            return grub_errno;
          write_mask = 0xffffffff;
index 4e929e0452eaa364a9c98cb62710d9fe6a0b95cd..62d3fb3988fdca7e9e449d367b46692f18fa7925 100644 (file)
@@ -31,7 +31,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 /* A simple implementation for signed numbers. */
 static int
-grub_strtosl (char *arg, char **end, int base)
+grub_strtosl (char *arg, const char ** const end, int base)
 {
   if (arg[0] == '-')
     return -grub_strtoul (arg + 1, end, base);
index 4be8107d553a1e2fa582fd292ba58e36312c2372..016a4d81835d513c9c2de2d72fac683bea3c51df 100644 (file)
@@ -136,7 +136,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
   ctx.height = ctx.width = ctx.depth = 0;
   if (argc)
     {
-      char *ptr;
+      const char *ptr;
       ptr = args[0];
       ctx.width = grub_strtoul (ptr, &ptr, 0);
       if (grub_errno)
index c3b578acf259e8bb76016371d32aa0d6d5cceca5..67bf37a9c3c79756f910e04c3fbbb378cfa0fec5 100644 (file)
@@ -969,7 +969,8 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
            for (p = vgp->lvs; p; p = p->next)
              {
                int cur_num;
-               char *num, *end;
+               char *num;
+               const char *end;
                if (!p->fullname)
                  continue;
                if (grub_strncmp (p->fullname, lv->fullname, len) != 0)
index 7b265c780c355263b7e5a1bad53af4bed406da04..0cbd0dd1629dbc5959fc6ba63f1e23ba03947a59 100644 (file)
@@ -38,7 +38,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
    at the number.  In case STR is not found, *P will be NULL and the
    return value will be 0.  */
 static grub_uint64_t
-grub_lvm_getvalue (char **p, const char *str)
+grub_lvm_getvalue (const char ** const p, const char *str)
 {
   *p = grub_strstr (*p, str);
   if (! *p)
@@ -63,12 +63,12 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
 #endif
 
 static int
-grub_lvm_check_flag (char *p, const char *str, const char *flag)
+grub_lvm_check_flag (const char *p, const char *str, const char *flag)
 {
   grub_size_t len_str = grub_strlen (str), len_flag = grub_strlen (flag);
   while (1)
     {
-      char *q;
+      const char *q;
       p = grub_strstr (p, str);
       if (! p)
        return 0;
@@ -105,7 +105,8 @@ grub_lvm_detect (grub_disk_t disk,
   char buf[GRUB_LVM_LABEL_SIZE];
   char vg_id[GRUB_LVM_ID_STRLEN+1];
   char pv_id[GRUB_LVM_ID_STRLEN+1];
-  char *metadatabuf, *p, *q, *vgname;
+  char *metadatabuf, *vgname;
+  const char *p, *q;
   struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
   struct grub_lvm_pv_header *pvh;
   struct grub_lvm_disk_locn *dlocn;
index c5c3d4bd3d5cc3344726d499ef12501267e8e808..dd42bc69116acf342d1b8e65561d7ec9559a0045 100644 (file)
@@ -39,7 +39,7 @@ static grub_size_t nvramsize;
 
 /* Parse signed value */
 static int
-grub_strtosl (const char *arg, char **end, int base)
+grub_strtosl (const char *arg, const char ** const end, int base)
 {
   if (arg[0] == '-')
     return -grub_strtoul (arg + 1, end, base);
@@ -120,7 +120,8 @@ nvram_set (void * data __attribute__ ((unused)))
   grub_memset (nvram, 0, nvramsize);
   FOR_SORTED_ENV (var)
   {
-    char *guid, *attr, *name, *varname;
+    const char *guid;
+    char *attr, *name, *varname;
     struct efi_variable *efivar;
     int len = 0;
     int i;
index 354dd7b73eead5e91e3835a11d43bc3542c003b0..7578bfbec925d86b94427f74523fb775c34bad16 100644 (file)
@@ -230,7 +230,7 @@ circprog_set_state (void *vself, int visible, int start,
 static int
 parse_angle (const char *value)
 {
-  char *ptr;
+  const char *ptr;
   int angle;
 
   angle = grub_strtol (value, &ptr, 10);
index d6829bb5e9070ca39931746c70771d35cbe85576..eae83086bcc0dc707671eaaacdfbda3484b4ca23 100644 (file)
@@ -484,7 +484,7 @@ parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *pr
          ptr++;
        }
 
-      num = grub_strtoul (ptr, (char **) &ptr, 0);
+      num = grub_strtoul (ptr, &ptr, 0);
       if (grub_errno)
        return grub_errno;
       if (sig)
index 2b85f4950bdf7fef23f5ea2ae1d1878b25eb84a7..88d39360da058a9d795d05ca1abad07c7753dfce 100644 (file)
@@ -134,7 +134,7 @@ struct grub_fs_block
 static grub_err_t
 grub_fs_blocklist_open (grub_file_t file, const char *name)
 {
-  char *p = (char *) name;
+  const char *p = name;
   unsigned num = 0;
   unsigned i;
   grub_disk_t disk = file->device->disk;
index 76e7fb22872bbf216fefa2feaac9650de59c8aed..b714c97b90fa63761d691f994a3328c3446f5933 100644 (file)
@@ -340,7 +340,8 @@ grub_isspace (int c)
 }
 
 unsigned long
-grub_strtoul (const char *str, char **end, int base)
+grub_strtoul (const char * restrict str, const char ** const restrict end,
+             int base)
 {
   unsigned long long num;
 
@@ -357,7 +358,8 @@ grub_strtoul (const char *str, char **end, int base)
 }
 
 unsigned long long
-grub_strtoull (const char *str, char **end, int base)
+grub_strtoull (const char * restrict str, const char ** const restrict end,
+              int base)
 {
   unsigned long long num = 0;
   int found = 0;
@@ -855,14 +857,14 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
        {
          if (fmt[0] == '0')
            zerofill = '0';
-         format1 = grub_strtoul (fmt, (char **) &fmt, 10);
+         format1 = grub_strtoul (fmt, &fmt, 10);
        }
 
       if (*fmt == '.')
        fmt++;
 
       if (grub_isdigit (*fmt))
-       format2 = grub_strtoul (fmt, (char **) &fmt, 10);
+       format2 = grub_strtoul (fmt, &fmt, 10);
 
       if (*fmt == '$')
        {
index e499147cbcbaa26a00f4076f191c691060ff5bf2..2c401b866c4be036dc13864e3254ea5015f0e671 100644 (file)
@@ -126,7 +126,7 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
       while (*ptr && grub_isalpha (*ptr))
        ptr++;
       partname_end = ptr; 
-      num = grub_strtoul (ptr, (char **) &ptr, 0) - 1;
+      num = grub_strtoul (ptr, &ptr, 0) - 1;
 
       curpart = 0;
       /* Use the first partition map type found.  */
index fd7744a6ff659138894ae2901e2de8ba682297fe..ccc185017ee0a4aeaf62bf4eee9d258d459df3fd 100644 (file)
@@ -375,7 +375,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
 
            case ARG_TYPE_INT:
              {
-               char *tail;
+               const char * tail;
 
                grub_strtoull (option, &tail, 0);
                if (tail == 0 || tail == option || *tail != '\0' || grub_errno)
index 412f26f17f0b1ffdd5d4972bed9201443f0f775c..15c0d99491c9eb540f2d3b9c2b90893dd973e2f4 100644 (file)
@@ -227,7 +227,7 @@ grub_json_getuint64 (grub_uint64_t *out, const grub_json_t *parent, const char *
 {
   grub_json_type_t type;
   const char *value;
-  char *end;
+  const char *end;
   grub_err_t ret;
 
   ret = get_value (&type, &value, parent, key);
@@ -249,7 +249,7 @@ grub_json_getint64 (grub_int64_t *out, const grub_json_t *parent, const char *ke
 {
   grub_json_type_t type;
   const char *value;
-  char *end;
+  const char *end;
   grub_err_t ret;
 
   ret = get_value (&type, &value, parent, key);
index ef56150ac770c6e6842057b31bc03baffa035f3d..05719ab2ccbc08dbf5aa2db3b011d4069d803150 100644 (file)
@@ -418,7 +418,7 @@ adjust_file (const char *in, grub_size_t len)
     }
   if (*comma != ',')
     return grub_legacy_escape (in, len);
-  part = grub_strtoull (comma + 1, (char **) &rest, 0);
+  part = grub_strtoull (comma + 1, &rest, 0);
   if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z')
     {
       subpart = rest[1] - 'a';
index 4afa99279a27d4ca462a2a27ab781a0e3f46a812..de9fda06f52786f98f9fc62373aeeb9305c79e11 100644 (file)
@@ -1062,7 +1062,7 @@ write_entry (struct output_buffer *outbuf,
                if (ptr[0] == 'h' && ptr[1] == 'd')
                  {
                    is_fd = 0;
-                   devn = grub_strtoul (ptr + 2, &ptr, 0);
+                   devn = grub_strtoul (ptr + 2, (const char **)&ptr, 0);
                    continue;
                  }
                if (grub_strncasecmp (ptr, "file=", 5) == 0)
@@ -1086,12 +1086,12 @@ write_entry (struct output_buffer *outbuf,
                if (ptr[0] == 'f' && ptr[1] == 'd')
                  {
                    is_fd = 1;
-                   devn = grub_strtoul (ptr + 2, &ptr, 0);
+                   devn = grub_strtoul (ptr + 2, (const char **)&ptr, 0);
                    continue;
                  }
                if (grub_isdigit (ptr[0]))
                  {
-                   part = grub_strtoul (ptr, &ptr, 0);
+                   part = grub_strtoul (ptr, (const char **)&ptr, 0);
                    continue;
                  }
                /* FIXME: isolinux, ntldr, cmldr, *dos, seg, hide
index 3730ed3824723a022ecd0d3c952f7115160d3a60..eb82391dbea34a1001fe7a86f4e5bd8f87dbca9f 100644 (file)
@@ -1615,7 +1615,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
        return grub_error (GRUB_ERR_BAD_ARGUMENT,
                           "unknown disk type name");
 
-      unit = grub_strtoul (arg, (char **) &arg, 10);
+      unit = grub_strtoul (arg, &arg, 10);
       if (! (arg && *arg >= 'a' && *arg <= 'z'))
        return grub_error (GRUB_ERR_BAD_ARGUMENT,
                           "only device specifications of form "
@@ -1633,7 +1633,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
   if (ctxt->state[OPENBSD_SERIAL_ARG].set)
     {
       struct grub_openbsd_bootarg_console serial;
-      char *ptr;
+      const char *ptr;
       unsigned port = 0;
       unsigned speed = 9600;
 
@@ -1735,7 +1735,7 @@ grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
       if (ctxt->state[NETBSD_SERIAL_ARG].set)
        {
          struct grub_netbsd_btinfo_serial serial;
-         char *ptr;
+         const char *ptr;
 
          grub_memset (&serial, 0, sizeof (serial));
          grub_strcpy (serial.devname, "com");
index ee95cd374b760b3fe92cbba464faf4250a1f628c..ac1fae72e3b4000a3c98964047ed335c433b2d7c 100644 (file)
@@ -944,7 +944,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 #endif /* GRUB_MACHINE_PCBIOS */
     if (grub_memcmp (argv[i], "mem=", 4) == 0)
       {
-       char *val = argv[i] + 4;
+       const char *val = argv[i] + 4;
 
        linux_mem_size = grub_strtoul (val, &val, 0);
 
index 47ea2945e4f019a27d67b6d545b8d149fd38cf6c..f56af7c501fbfd86cbd9edb5a8519cbcae80d92a 100644 (file)
@@ -259,7 +259,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       }
     else if (grub_memcmp (argv[i], "mem=", 4) == 0)
       {
-       char *val = argv[i] + 4;
+       const char *val = argv[i] + 4;
 
        linux_mem_size = grub_strtoul (val, &val, 0);
 
index 6329ec01038cd6baafa32bcc8d6ad4c4915d8f9a..27afcaacbcea782a132d31c838d0a16a8d7ea0f1 100644 (file)
@@ -25,7 +25,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
                 grub_off_t off, grub_size_t sz)
 {
   char *buf;
-  char *ptr;
+  const char *ptr;
   int has_paddr = 0;
 
   grub_errno = GRUB_ERR_NONE;
index 6a31cbae325aa95c7003e6f7e28bbfb969b12db5..b569cb23b5a802a3f24708c7fbbe9682b28bbab5 100644 (file)
@@ -423,7 +423,7 @@ static grub_err_t
 grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)),
                 int argc, char **args)
 {
-  char * str;
+  const char *str;
   struct badram_entry entry;
 
   if (argc != 1)
@@ -465,7 +465,7 @@ static grub_uint64_t
 parsemem (const char *str)
 {
   grub_uint64_t ret;
-  char *ptr;
+  const char *ptr;
 
   ret = grub_strtoul (str, &ptr, 0);
 
index ec3647f9a0c273b2d0fb5b5d516ad9e15497c845..b616cf40b1e440d5cac8b3cb409731c2fe4640bd 100644 (file)
@@ -107,7 +107,7 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
          return GRUB_ERR_NONE;
        }
       ptr += sizeof ("HTTP/1.1 ") - 1;
-      code = grub_strtoul (ptr, &ptr, 10);
+      code = grub_strtoul (ptr, (const char **)&ptr, 10);
       if (grub_errno)
        return grub_errno;
       switch (code)
@@ -134,7 +134,7 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
       == 0 && !data->size_recv)
     {
       ptr += sizeof ("Content-Length: ") - 1;
-      file->size = grub_strtoull (ptr, &ptr, 10);
+      file->size = grub_strtoull (ptr, (const char **)&ptr, 10);
       data->size_recv = 1;
       return GRUB_ERR_NONE;
     }
index f82ac15b4ecbcf78bb57ae02cd2e10c0f282ad1c..c42f0f4f71d99a6c8e1b6f2f207f2d64a4328be9 100644 (file)
@@ -406,7 +406,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
   for (i = 0; i < 4; i++)
     {
       unsigned long t;
-      t = grub_strtoul (ptr, (char **) &ptr, 0);
+      t = grub_strtoul (ptr, &ptr, 0);
       if (grub_errno)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -453,7 +453,7 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
          ptr++;
          continue;
        }
-      t = grub_strtoul (ptr, (char **) &ptr, 16);
+      t = grub_strtoul (ptr, &ptr, 16);
       if (grub_errno)
        {
          grub_errno = GRUB_ERR_NONE;
@@ -563,7 +563,7 @@ grub_net_resolve_net_address (const char *name,
       addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
       if (*rest == '/')
        {
-         addr->ipv4.masksize = grub_strtoul (rest + 1, (char **) &rest, 0);
+         addr->ipv4.masksize = grub_strtoul (rest + 1, &rest, 0);
          if (!grub_errno && *rest == 0)
            return GRUB_ERR_NONE;
          grub_errno = GRUB_ERR_NONE;
@@ -579,7 +579,7 @@ grub_net_resolve_net_address (const char *name,
       addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
       if (*rest == '/')
        {
-         addr->ipv6.masksize = grub_strtoul (rest + 1, (char **) &rest, 0);
+         addr->ipv6.masksize = grub_strtoul (rest + 1, &rest, 0);
          if (!grub_errno && *rest == 0)
            return GRUB_ERR_NONE;
          grub_errno = GRUB_ERR_NONE;
index d5e0c79a70e1e13f1c2f7ad2029274138d637e25..da66ad891801024394f907e4f5bbeb3c67c23b21 100644 (file)
@@ -170,8 +170,7 @@ grub_menu_set_timeout (int timeout)
 static int
 get_and_remove_first_entry_number (const char *name)
 {
-  const char *val;
-  char *tail;
+  const char *val, *tail;
   int entry;
 
   val = grub_env_get (name);
index 2be654ca3bd6262e310205e73d26ea2ff7ce44be..3b2c9de2496aa7ebfcd2a22d7fcf992efd238018 100644 (file)
@@ -194,7 +194,7 @@ grub_util_fd_open (const char *dev, int flg)
     p1 = dev + strlen (dev);
   else
     {
-      unit = grub_strtoul (p1 + 1, (char **) &p2, 16);
+      unit = grub_strtoul (p1 + 1, &p2, 16);
       if (p2 && *p2 == '/')
        flags = grub_strtoul (p2 + 1, 0, 16);
     }
index a697bcb4d8d91cd97343179fe7977d6806d4191e..a8afc0c9408d0ae8b8811054e4ed53d1c9852a6d 100644 (file)
@@ -113,7 +113,7 @@ grub_util_get_dm_node_linear_info (dev_t dev,
   void *next = NULL;
   uint64_t length, start;
   char *target, *params;
-  char *ptr;
+  const char *ptr;
   int major = 0, minor = 0;
   int first = 1;
   grub_disk_addr_t partstart = 0;
index ee299fd0ea65b433765803d46e00d255031b3a91..8cc61ee7d781a559a67e2a506e5039209e347532 100644 (file)
@@ -122,7 +122,7 @@ replace_scope (struct grub_script_scope *new_scope)
 grub_err_t
 grub_script_break (grub_command_t cmd, int argc, char *argv[])
 {
-  char *p = 0;
+  const char *p = NULL;
   unsigned long count;
 
   if (argc == 0)
@@ -154,7 +154,7 @@ grub_err_t
 grub_script_shift (grub_command_t cmd __attribute__((unused)),
                   int argc, char *argv[])
 {
-  char *p = 0;
+  const char *p = NULL;
   unsigned long n = 0;
 
   if (! scope)
@@ -215,7 +215,7 @@ grub_err_t
 grub_script_return (grub_command_t cmd __attribute__((unused)),
                    int argc, char *argv[])
 {
-  char *p;
+  const char *p = NULL;
   unsigned long n;
 
   if (! scope || argc > 1)
index db80b3ba0fb25ee96397259827d93054e8c7cd57..f9271b0923937aa4e708a678727f418dea07e5f3 100644 (file)
@@ -269,7 +269,7 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 
   if (state[OPTION_BASE_CLOCK].set)
     {
-      char *ptr;
+      const char *ptr;
       config.base_clock = grub_strtoull (state[OPTION_BASE_CLOCK].arg, &ptr, 0);
       if (grub_errno)
        return grub_errno;
index d317efa368d846963743a243fd672026a2221933..0e9de7f8fa9fe03d17c4e142c927222f3fb99b37 100644 (file)
@@ -737,7 +737,7 @@ grub_cmd_terminfo (grub_extcmd_context_t ctxt, int argc, char **args)
 
   if (state[OPTION_GEOMETRY].set)
     {
-      char *ptr = state[OPTION_GEOMETRY].arg;
+      const char *ptr = state[OPTION_GEOMETRY].arg;
       w = grub_strtoul (ptr, &ptr, 0);
       if (grub_errno)
        return grub_errno;
index 7da615ff33e16bb7c3cae15190f52e3ccd8c0655..5488ab26b439262d89d2ba39eed454c36de62ac1 100644 (file)
@@ -25,7 +25,7 @@ static void
 strtoull_testcase (const char *input, int base, unsigned long long expected,
                   int num_digits, grub_err_t error)
 {
-  char *output;
+  const char *output;
   unsigned long long value;
   grub_errno = 0;
   value = grub_strtoull(input, &output, base);
index ee48eb7a726fbea8177a579047e521ff4674d5ce..cd5a8b4ae82ea583a6e0834195432a87119c8dae 100644 (file)
@@ -243,11 +243,29 @@ grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
     - (int) grub_tolower ((grub_uint8_t) *s2);
 }
 
-unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base);
-unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base);
+/*
+ * Note that these differ from the C standard's definitions of strtol,
+ * strtoul(), and strtoull() by the addition of two const qualifiers on the end
+ * pointer, which make the declaration match the *semantic* requirements of
+ * their behavior.  This means that instead of:
+ *
+ *  char *s = "1234 abcd";
+ *  char *end;
+ *  unsigned long l;
+ *
+ *  l = grub_strtoul(s, &end, 10);
+ *
+ * We must one of:
+ *
+ *  const char *end;
+ *  ... or ...
+ *  l = grub_strtoul(s, (const char ** const)&end, 10);
+ */
+unsigned long EXPORT_FUNC(grub_strtoul) (const char * restrict str, const char ** const restrict end, int base);
+unsigned long long EXPORT_FUNC(grub_strtoull) (const char * restrict str, const char ** const restrict end, int base);
 
 static inline long
-grub_strtol (const char *str, char **end, int base)
+grub_strtol (const char * restrict str, const char ** const restrict end, int base)
 {
   int negative = 0;
   unsigned long long magnitude;
index f14e02d97279e542174096067b842346eb807b76..7f14620cd490af6bb54b5d38470b4d771c94af30 100644 (file)
@@ -538,7 +538,7 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
 static error_t 
 argp_parser (int key, char *arg, struct argp_state *state)
 {
-  char *p;
+  const char *p;
 
   switch (key)
     {