https://sourceware.org/bugzilla/show_bug.cgi?id=34997

            Bug ID: 34997
           Summary: fold_binary() in ld/ldexp.c shifts a 64-bit bfd_vma by
                    the right-hand value of a << or >> expression without
                    checking that it is less than 64. A linker script
                    expression with a large shift count causes undefined
                    behavior (reported by UBSan at lines 655 an
           Product: binutils
           Version: 2.48 (HEAD)
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: emily.west286 at gmail dot com
  Target Milestone: ---

Created attachment 17270
  --> https://sourceware.org/bugzilla/attachment.cgi?id=17270&action=edit
Dockerfile for reproduction environment

Component: ld

Version: binutils-gdb master, commit 819dfa7b5325656ccb58ea5f65761982bb7844e3
on the master branch

The problem happens while the script is being parsed. exp_binop folds constant
expressions right away, so no valid script is needed.  

UBSan output:  
ld/ldexp.c:656:4: runtime error: shift exponent 100000000000000 is too large
for 64-bit type 'bfd_vma' (aka 'unsigned long')
ld/ldexp.c:655:4: runtime error: shift exponent 73 is too large for 64-bit type
'bfd_vma' (aka 'unsigned long')

Stack trace:  
#1 fold_binary          ld/ldexp.c:656
#2 exp_fold_tree_1      ld/ldexp.c:1109
#3 exp_fold_tree_no_dot ld/ldexp.c:1344
#4 exp_value_fold       ld/ldexp.c:1350
#5 exp_binop            ld/ldexp.c:1378
#6 yyparse              ld/ldgram.y:986
#7 load_symbols         ld/ldlang.c:3256
#8 open_input_bfds      ld/ldlang.c:3836
#9 lang_process         ld/ldlang.c:8635
#10 main                ld/ldmain.c:1092

Reproducers attached:  
minimized reproducers, and a crafted linker script that targets the bug.
The relevant part is 0>>100000000000000.

ld treats the file as a linker script, hits the bad shift, then stops with a
syntax error.

Build:  
clang, -O1, ASan and UBSan (shift check enabled)
A Dockerfile is attached that provides the environment.

Impact:  
Low. On x86-64 the CPU only uses the low 6 bits of the shift count, so the
result is silently wrong rather than an error. Other compilers or optimization
levels may behave differently. Linker scripts are usually trusted input.

Suggested fix:  
Check the shift count before shifting in fold_binary, for example return 0 (or
report an error) when rhs.value >= 64.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to