Hi,
While fuzzing fig2dev with American Fuzzy Lop, I found a Stack-based Buffer
Overflow in the calc_arrow() function, in bound.c.
Attaching a reproducer, issue can be reproduced by running:
fig2dev -L box test01
=================================================================
==28368==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff6e149530 at pc 0x0000005247b7 bp 0x7fff6e148ca0 sp 0x7fff6e148c98
WRITE of size 4 at 0x7fff6e149530 thread T0
#0 0x5247b6 in calc_arrow /home/fcambus/fig2dev/fig2dev/bound.c:956:15
#1 0x5165e3 in arrow_bound /home/fcambus/fig2dev/fig2dev/bound.c:742:6
#2 0x51d861 in line_bound /home/fcambus/fig2dev/fig2dev/bound.c:454:6
#3 0x519b50 in compound_bound /home/fcambus/fig2dev/fig2dev/bound.c:316:3
#4 0x52cd09 in main /home/fcambus/fig2dev/fig2dev/fig2dev.c:452:2
#5 0x7f6f5f826b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#6 0x41b279 in _start (/home/fcambus/fig2dev/fig2dev/fig2dev+0x41b279)
Address 0x7fff6e149530 is located in stack of thread T0 at offset 496 in frame
#0 0x515a3f in arrow_bound /home/fcambus/fig2dev/fig2dev/bound.c:713
This frame has 6 object(s):
[32, 36) 'p1x' (line 718)
[48, 52) 'p1y' (line 718)
[64, 68) 'dum' (line 719)
[80, 84) 'npts' (line 720)
[96, 496) 'arrowpts' (line 721) <== Memory access at offset 496 overflows this variable
[560, 960) 'arrowdumpts' (line 721)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/fcambus/fig2dev/fig2dev/bound.c:956:15 in calc_arrow
Shadow bytes around the buggy address:
0x10006dc21250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006dc21260: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f2 04 f2
0x10006dc21270: 04 f2 04 f2 00 00 00 00 00 00 00 00 00 00 00 00
0x10006dc21280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006dc21290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10006dc212a0: 00 00 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 00 00
0x10006dc212b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006dc212c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006dc212d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006dc212e0: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x10006dc212f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==28368==ABORTING
This issue got assigned CVE-2019-14275.
The shape of a circle or half-circle arrowhead would be approximated in calc_arrow() in bound.c by 40 + mag/4 points. The routines that used calc_arrow() passed arrays of size 50, hence at a magnification >= 42 the address sanitizer would detect an error. For much larger magnifications, fig2dev would segfault. A fix would be, to allocate arrays in calc_arrow and pass these arrays back to the caller. A quicker fix is to use a fixed number of points. This is done with commit 03ea45.
Since the arrowheads computed by calc_arrow() are used in only a few drivers, for metapost, postscript, pict2e and svg output languages, which all know how to draw arcs or circles, another option is to put code for drawing these arrowheads into the respective drivers.
Fixed with release 3.2.7b.