This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] readelf: Add bounds check before each CFA op that takes an argument.


Some CFA ops don't take any arguments, for those it is valid to be at the
end of the data block.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 src/ChangeLog |  5 +++++
 src/readelf.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 7960496..e39fc3e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2014-12-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_cfa_program): Add bounds check before each op that
+	takes at least one argument.
+
 2014-12-16  Mark Wielaard  <mjw@redhat.com>
 
 	* readelf.c (print_debug_line_section): Correct overflow check for
diff --git a/src/readelf.c b/src/readelf.c
index 9c62853..b3eaccb 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4971,11 +4971,15 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    puts ("     nop");
 	    break;
 	  case DW_CFA_set_loc:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    op1 += vma_base;
 	    printf ("     set_loc %" PRIu64 "\n", op1 * code_align);
 	    break;
 	  case DW_CFA_advance_loc1:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
 		    *readp, pc += *readp * code_align);
 	    ++readp;
@@ -4995,6 +4999,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, pc += op1 * code_align);
 	    break;
 	  case DW_CFA_offset_extended:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5004,19 +5010,27 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, regname (op1), op2 * data_align);
 	    break;
 	  case DW_CFA_restore_extended:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
 		    op1, regname (op1));
 	    break;
 	  case DW_CFA_undefined:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
 	    break;
 	  case DW_CFA_same_value:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
 	    break;
 	  case DW_CFA_register:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5031,6 +5045,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    puts ("     restore_state");
 	    break;
 	  case DW_CFA_def_cfa:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5039,15 +5055,21 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, regname (op1), op2);
 	    break;
 	  case DW_CFA_def_cfa_register:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
 		    op1, regname (op1));
 	    break;
 	  case DW_CFA_def_cfa_offset:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
 	    break;
 	  case DW_CFA_def_cfa_expression:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);	/* Length of DW_FORM_block.  */
 	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
 	    if ((uint64_t) (endp - readp) < op1)
@@ -5061,6 +5083,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    readp += op1;
 	    break;
 	  case DW_CFA_expression:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5074,6 +5098,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    readp += op2;
 	    break;
 	  case DW_CFA_offset_extended_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5083,6 +5109,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, regname (op1), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5091,11 +5119,14 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, regname (op1), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_offset_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_sleb128 (sop1, readp, endp);
 	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
 	    break;
 	  case DW_CFA_val_offset:
-	    // XXX overflow check
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5104,7 +5135,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, op2 * data_align);
 	    break;
 	  case DW_CFA_val_offset_sf:
-	    // XXX overflow check
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5113,6 +5145,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		    op1, sop2 * data_align);
 	    break;
 	  case DW_CFA_val_expression:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
@@ -5136,6 +5170,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    puts ("     GNU_window_save");
 	    break;
 	  case DW_CFA_GNU_args_size:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     args_size %" PRIu64 "\n", op1);
 	    break;
@@ -5149,6 +5185,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
       else if (opcode < DW_CFA_restore)
 	{
 	  uint64_t offset;
+	  if ((uint64_t) (endp - readp) < 1)
+	    goto invalid;
 	  get_uleb128 (offset, readp, endp);
 	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
 		  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]