Skip to content

[rtext] Fix GetCodepoint() size on invalid sequences reading past the string end - #6348

Open
jayhemnani9910 wants to merge 1 commit into
raysan5:masterfrom
jayhemnani9910:fix-get-codepoint-invalid-size
Open

jayhemnani9910 wants to merge 1 commit into
raysan5:masterfrom
jayhemnani9910:fix-get-codepoint-invalid-size

Conversation

@jayhemnani9910

Copy link
Copy Markdown
Contributor

On an invalid or cut-off UTF-8 sequence, GetCodepoint() reports a size that includes the byte that broke the sequence. When that byte is the string's '\0', a caller that steps by the size walks past the end:

const char *in = "ok \xe2\x82";   // ends in a cut-off 3-byte sequence
char *text = malloc(strlen(in) + 1); strcpy(text, in);
int size = 0;
for (const char *p = text; *p != '\0'; p += size) GetCodepoint(p, &size);
// master, -fsanitize=address: heap-buffer-overflow, READ of size 1

\xe2\x82 returns '?' with size 3, so p jumps over the terminator. The same happens for a lone lead byte before '\0' (size 2) and for 4-byte sequences (size 4).

The size is now the number of bytes before the one that broke the sequence, so the bad byte is read again as the start of the next character: "\xe2\x82" gives one '?' of size 2 and stops at '\0'. Lead bytes that can't start a sequence here (E0 followed by 80-9F, ED A0-BF surrogates, F0 80-8F, F4 90-BF) consume 1 byte. Valid input decodes as before.

Tested by stepping through 5000 random strings built from valid, cut-off, surrogate, overlong and stray bytes and comparing the codepoints with Python's bytes.decode("utf-8", "replace"), which follows the Unicode recommendation of one replacement per maximal invalid subpart:

  • master: 3690 of 5000 differ
  • fixed: 0 differ, and the loop above runs clean under AddressSanitizer

Builds with PLATFORM_MEMORY.

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

1 participant