BYVoid / OpenCC

Conversion between Traditional and Simplified Chinese
https://opencc.byvoid.com/
Apache License 2.0
8.46k stars 982 forks source link

Stack buffer overflow in UTF8Util.hpp #799

Open morningbread opened 1 year ago

morningbread commented 1 year ago

Hi, i found an stack overflow vulnerability in UTF8Util.hpp.

I put the POC in the attachment, prove it like this. (compile opencc_phrase_extract with address sanitizer). ./opencc_phrase_extract -o tmp.txt minpoc

Then, ASAN would catch the error:

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/work/OpenCC/src/UTF8Util.hpp:49:15 in opencc::UTF8Util::NextCharLengthNoException(char const*)                                                                                                               Shadow bytes around the buggy address:
  0x0c067fff8080: 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa
  0x0c067fff8090: fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00
  0x0c067fff80a0: 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
  0x0c067fff80b0: 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa
  0x0c067fff80c0: fa fa 00 00 00 fa fa fa fd fd fd fd fa fa 00 00
=>0x0c067fff80d0: 00 00 fa fa fd fd fd fd fa[fa]00 00 00 07 fa fa
  0x0c067fff80e0: 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa
  0x0c067fff80f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

When the last input character is 0xF0/0xE0/0xF8/0xFC/0xFE, the NextCharLengthNoException() will return a value greater than 1. Then, it will read more memory in the stack, cause a stack overflow.

  static size_t NextCharLengthNoException(const char* str) {
    char ch = *str;
    if ((ch & 0xF0) == 0xE0) {
      return 3;
    } else if ((ch & 0x80) == 0x00) {
      return 1;
    } else if ((ch & 0xE0) == 0xC0) {
      return 2;
    } else if ((ch & 0xF8) == 0xF0) {
      return 4;
    } else if ((ch & 0xFC) == 0xF8) {
      return 5;
    } else if ((ch & 0xFE) == 0xFC) {
      return 6;
    }
    return 0;
  }

minpoc.zip