[binutils-gdb] RISC-V: avoid buffer underrun in subset parsing

Jan Beulich via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=952275b4a6c44fee709cb47236df9f604327d1d4

commit 952275b4a6c44fee709cb47236df9f604327d1d4
Author: Jan Beulich <[email protected]>
Date:   Fri Jun 5 11:11:25 2026 +0200

    RISC-V: avoid buffer underrun in subset parsing
    
    In both instances 'p' can be the first character. Inspecting the character
    immediately ahead of it is then UB.
    
    To increase similarity between the two checks (each), also move the
    increment of q past the check for the (bogus) "<number>p" ending.
    
    Correct indentation in nearby code, where it being wrong is actively
    misleading.
    
    Reviewed-by: Jiawei <[email protected]>

Diff:
---
 bfd/elfxx-riscv.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 8e56322b512..c0439102e8d 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -2113,25 +2113,27 @@ riscv_parse_extensions (riscv_parse_subset_t *rps,
 		find_any_version = true;
 	      else if (find_any_version
 		       && !find_minor_version
+		       && q > subset
 		       && *q == 'p'
 		       && ISDIGIT (*(q - 1)))
-	      find_minor_version = true;
+		find_minor_version = true;
 	      else
 		break;
 	    }
-	  q++;
 
 	  /* Check if the end of extension is 'p' or not.  If yes, then
 	     the second letter from the end cannot be number.  */
-	  if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
+	  if (q > subset && *q == 'p' && ISDIGIT (*(q - 1)))
 	    {
-	      *q = '\0';
+	      q[1] = '\0';
 	      rps->error_handler
 		(_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
 		 arch, subset);
 	      free (subset);
 	      return NULL;
 	    }
+
+	  q++;
 	}
 
       int major_version = RISCV_UNKNOWN_VERSION;
@@ -2672,20 +2674,19 @@ riscv_update_subset1 (riscv_parse_subset_t *rps,
 	    find_any_version = true;
 	  else if (find_any_version
 		   && !find_minor_version
+		   && q > subset
 		   && *q == 'p'
 		   && ISDIGIT (*(q - 1)))
 	    find_minor_version = true;
 	  else
 	    break;
 	}
-      if (len > 0)
-	q++;
 
       /* Check if the end of extension is 'p' or not.  If yes, then
 	 the second letter from the end cannot be number.  */
-      if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2)))
+      if (q > subset && *q == 'p' && ISDIGIT (*(q - 1)))
 	{
-	  *q = '\0';
+	  q[1] = '\0';
 	  rps->error_handler
 	    (_("%sinvalid ISA extension `%s' ends with <number>p in %s `%s'"),
 	       errmsg_internal, subset, errmsg_caller, implicit_exts);
@@ -2693,6 +2694,9 @@ riscv_update_subset1 (riscv_parse_subset_t *rps,
 	  return false;
 	}
 
+      if (len > 0)
+	q++;
+
       end_of_version =
 	riscv_parsing_subset_version (q, &major_version, &minor_version);
       *q = '\0';
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.