On x86, PIC_OFFSET_TABLE_REGNUM calls a function (ix86_use_pseudo_pic_reg) so its value can theoretically change between its first and second use in the following conditional:

       if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
          && fixed_regs[PIC_OFFSET_TABLE_REGNUM])

Since the macro can return -1 on x86, the second use can cause an out of bounds access.

In practice ix86_use_pseudo_pic_reg() is probably a pure function, since we really shouldn't be changing the semantics of the pic register mid-flight, but it's probably safer to just avoid calling the function twice.

OK pending tests?
+       * builtins.c (expand_builtin_nonlocal_goto): Avoid evaluating
+       PIC_OFFSET_TABLE_REGNUM twice.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 058ecc3..d4f7e94 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1101,8 +1101,8 @@ expand_builtin_nonlocal_goto (tree exp)
         to targets with a nonlocal_goto pattern; they are free
         to implement it in their own way.  Note also that this is
         a no-op if the GP register is a global invariant.)  */
-      if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
-         && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
+      unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
+      if (regnum != INVALID_REGNUM && fixed_regs[regnum])
        emit_use (pic_offset_table_rtx);
 
       emit_indirect_jump (r_label);

Reply via email to