Browse Source

Fix storing the line length in the hash chain.

The length is stored as the first byte in the output from
compile_line. As the data pointer is char, if char is signed then
length could be negative resulting in undefined behaviour. This
commit fixes the issue by reading and writing that byte as a
uint8_t.

This bug was caused by 2a00ca79f6.
Previously, the entries could only be a maximum of 128 bytes, and
would not be negative on platforms with signed chars. That
commit was made to support long emoji entries, especially for
non-Latin languages where the utf-8 representations could be
longer than 128 bytes.

This change also adds some documentation to make it clearer what
is going on. NOTE: The code should really be using actual struct
objects instead of writing to opaque char buffers.

Reported by Reef Turner <[email protected]>
master
Reece H. Dunn 8 years ago
parent
commit
ebfa320956
1 changed files with 12 additions and 3 deletions
  1. 12
    3
      src/libespeak-ng/compiledict.c

+ 12
- 3
src/libespeak-ng/compiledict.c View File

static int debug_flag = 0; static int debug_flag = 0;
static int error_need_dictionary = 0; static int error_need_dictionary = 0;


// A hash chain is a linked-list of hash chain entry objects:
// struct hash_chain_entry {
// hash_chain_entry *next_entry;
// // dict_line output from compile_line:
// uint8_t length;
// char contents[length];
// };
static char *hash_chains[N_HASH_DICT]; static char *hash_chains[N_HASH_DICT];

static char letterGroupsDefined[N_LETTER_GROUPS]; static char letterGroupsDefined[N_LETTER_GROUPS];


MNEM_TAB mnem_rules[] = { MNEM_TAB mnem_rules[] = {
length += ix; length += ix;
} }
} }
dict_line[0] = length;
*((uint8_t *)dict_line) = (uint8_t)length;


return length; return length;
} }
p = hash_chains[hash]; p = hash_chains[hash];


while (p != NULL) { while (p != NULL) {
length = *(p+sizeof(char *));
length = *(uint8_t *)(p+sizeof(char *));
fwrite(p+sizeof(char *), length, 1, f_out); fwrite(p+sizeof(char *), length, 1, f_out);
memcpy(&p, p, sizeof(char *)); memcpy(&p, p, sizeof(char *));
} }
FILE *f_in; FILE *f_in;
char buf[200]; char buf[200];
char fname[sizeof(path_home)+45]; char fname[sizeof(path_home)+45];
char dict_line[200];
char dict_line[256]; // length is uint8_t, so an entry can't take up more than 256 bytes


text_mode = 0; text_mode = 0;




memcpy(p, &hash_chains[hash], sizeof(char *)); memcpy(p, &hash_chains[hash], sizeof(char *));
hash_chains[hash] = p; hash_chains[hash] = p;
// NOTE: dict_line[0] is the entry length (0-255)
memcpy(p+sizeof(char *), dict_line, length); memcpy(p+sizeof(char *), dict_line, length);
count++; count++;
} }

Loading…
Cancel
Save