Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SECURITY] stack-buffer-overflow in dictionary.c #1913

Open
RootUp opened this issue May 5, 2024 · 0 comments
Open

[SECURITY] stack-buffer-overflow in dictionary.c #1913

RootUp opened this issue May 5, 2024 · 0 comments

Comments

@RootUp
Copy link

RootUp commented May 5, 2024

Summary

While fuzzing espeak-ng it was found that the application suffers from stack-buffer-overflow via a crafted file under RemoveEnding function, which is located in the dictionary.c

ASAN

==3874241==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffff404115f at pc 0x000000434862 bp 0x7ffff403e2a0 sp 0x7ffff403da48
READ of size 5 at 0x7ffff404115f thread T1
    #0 0x434861 in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long) (/espeak-ng/build/src/espeak-ng+0x434861)
    #1 0x434c6a in bcmp (/espeak-ng/build/src/espeak-ng+0x434c6a)
    #2 0x505b29 in RemoveEnding /espeak-ng/src/libespeak-ng/dictionary.c:2963:10
    #3 0x564693 in TranslateWord3 /espeak-ng/src/libespeak-ng/translateword.c:444:17
    #4 0x553871 in TranslateWord /espeak-ng/src/libespeak-ng/translate.c:150:14
    #5 0x55cae2 in TranslateWord2 /espeak-ng/src/libespeak-ng/translate.c:404:11
    #6 0x559e00 in TranslateClause /espeak-ng/src/libespeak-ng/translate.c:1594:17
    #7 0x5405ca in SpeakNextClause /espeak-ng/src/libespeak-ng/synthesize.c:1560:2
    #8 0x57ea73 in Synthesize /espeak-ng/src/libespeak-ng/speech.c:455:2
    #9 0x588e9b in process_espeak_command /espeak-ng/src/libespeak-ng/espeak_command.c:316:3
    #10 0x586304 in say_thread /espeak-ng/src/libespeak-ng/fifo.c:355:6
    #11 0x7ffff7c6d608 in start_thread /build/glibc-e2p3jK/glibc-2.31/nptl/pthread_create.c:477:8
    #12 0x7ffff7b65352 in clone /build/glibc-e2p3jK/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Address 0x7ffff404115f is located in stack of thread T1 at offset 5663 in frame
    #0 0x5542df in TranslateClause /espeak-ng/src/libespeak-ng/translate.c:923

  This frame has 18 object(s):
    [32, 36) 'fc.i.i.i' (line 742)
    [48, 52) 'nc.i.i.i' (line 743)
    [64, 68) 'new_c.i.i' (line 786)
    [80, 84) 'c2.i.i' (line 786)
    [96, 100) 'next2.i' (line 837)
    [112, 116) 'cc' (line 926)
    [128, 132) 'prev_in' (line 929)
    [144, 148) 'prev_out' (line 930)
    [160, 164) 'next_in' (line 932)
    [176, 180) 'charix_top' (line 955)
    [192, 1800) 'charix' (line 957)
    [1936, 5536) 'words' (line 958)
    [5664, 6464) 'sbuf' (line 962) <== Memory access at offset 5663 partially underflows this variable
    [6592, 6596) 'tone' (line 965)
    [6608, 6612) 'next2_in' (line 1274)
    [6624, 6628) 'c_temp' (line 1489)
    [6640, 6790) 'number_buf' (line 1492)
    [6864, 7464) 'num_wtab' (line 1493)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
Thread T1 created by T0 here:
    #0 0x480b9a in pthread_create (/espeak-ng/build/src/espeak-ng+0x480b9a)
    #1 0x585bb6 in fifo_init /espeak-ng/src/libespeak-ng/fifo.c:91:9
    #2 0x57d979 in espeak_ng_InitializeOutput /espeak-ng/src/libespeak-ng/speech.c:277:50

SUMMARY: AddressSanitizer: stack-buffer-overflow (/espeak-ng/build/src/espeak-ng+0x434861) in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long)
Shadow bytes around the buggy address:
  0x10007e8001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e8001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e8001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e800200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e800210: 00 00 00 00 00 00 00 00 00 00 00 00 f2 f2 f2 f2
=>0x10007e800220: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2[f2]00 00 00 00
  0x10007e800230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e800240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e800250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e800260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e800270: 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
  Shadow gap:              cc
==3874241==ABORTING

Code Snippet

https://github.com/espeak-ng/espeak-ng/blob/master/src/libespeak-ng/dictionary.c#L2963

				const char *p;
				for (i = 0; (p = add_e_additions[i]) != NULL; i++) {
					int len = strlen(p);
					if (memcmp(p, &word_end[1-len], len) == 0) {
						end_flags |= FLAG_SUFX_E_ADDED;
						break;
					}
				}
			}

The problem lies in the second argument which is passed to memcmp, which is &word_end[1-len]. If len is greater than or equal to the length of the word_end buffer, this will result in an out-of-bounds access successfully resulting to stack buffer overflow.

Proof-of-concept: sof.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant