hnj_hyphen_hyphword: fix buffer overflow (#13)
* Fix buffer overflow * hnj_hyphen_hyphword: rewrite, improve overflow checking * hnj_hyphen_hyphword: add test to detect overflows
This commit is contained in:
parent
726a506ef1
commit
a8d50da0cc
|
@ -67,7 +67,7 @@ main(int argc, char** argv)
|
||||||
char *hyphens;
|
char *hyphens;
|
||||||
char *lcword;
|
char *lcword;
|
||||||
char *hyphword;
|
char *hyphword;
|
||||||
char hword[BUFSIZE * 2];
|
char *hword;
|
||||||
int arg = 1;
|
int arg = 1;
|
||||||
int optd = 1;
|
int optd = 1;
|
||||||
int optn = 0;
|
int optn = 0;
|
||||||
|
@ -151,12 +151,16 @@ main(int argc, char** argv)
|
||||||
rep = NULL;
|
rep = NULL;
|
||||||
pos = NULL;
|
pos = NULL;
|
||||||
cut = NULL;
|
cut = NULL;
|
||||||
|
|
||||||
|
/* set minimum required output buffer size (2 * word_size) */
|
||||||
|
hword = (char *) malloc((n-1)*2);
|
||||||
hword[0] = '\0';
|
hword[0] = '\0';
|
||||||
|
|
||||||
if ((!optd && hnj_hyphen_hyphenate(dict, lcword, n-1, hyphens)) ||
|
if ((!optd && hnj_hyphen_hyphenate(dict, lcword, n-1, hyphens)) ||
|
||||||
(optd && hnj_hyphen_hyphenate2(dict, lcword, n-1, hyphens, hword, &rep, &pos, &cut))) {
|
(optd && hnj_hyphen_hyphenate2(dict, lcword, n-1, hyphens, hword, &rep, &pos, &cut))) {
|
||||||
free(hyphens);
|
free(hyphens);
|
||||||
free(lcword);
|
free(lcword);
|
||||||
|
free(hword);
|
||||||
fprintf(stderr, "hyphenation error\n");
|
fprintf(stderr, "hyphenation error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -202,6 +206,7 @@ main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
free(hyphens);
|
free(hyphens);
|
||||||
free(lcword);
|
free(lcword);
|
||||||
|
free(hword);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(wtclst);
|
fclose(wtclst);
|
||||||
|
|
45
hyphen.c
45
hyphen.c
|
@ -39,6 +39,7 @@
|
||||||
#include <stdlib.h> /* for NULL, malloc */
|
#include <stdlib.h> /* for NULL, malloc */
|
||||||
#include <stdio.h> /* for fprintf */
|
#include <stdio.h> /* for fprintf */
|
||||||
#include <string.h> /* for strdup */
|
#include <string.h> /* for strdup */
|
||||||
|
#include <limits.h> /* for INT_MAX */
|
||||||
|
|
||||||
#ifdef UNX
|
#ifdef UNX
|
||||||
#include <unistd.h> /* for exit */
|
#include <unistd.h> /* for exit */
|
||||||
|
@ -1073,23 +1074,41 @@ int hnj_hyphen_norm(const char *word, int word_size, char * hyphens,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the word with all possible hyphenations (output: hyphword) */
|
/* get the word with all possible hyphenations (output: hyphword) */
|
||||||
void hnj_hyphen_hyphword(const char * word, int l, const char * hyphens,
|
void hnj_hyphen_hyphword(const char * word, int word_size, const char * hyphens,
|
||||||
char * hyphword, char *** rep, int ** pos, int ** cut)
|
char * hyphword, char *** rep, int ** pos, int ** cut)
|
||||||
{
|
{
|
||||||
int hyphenslen = l + 5;
|
|
||||||
|
|
||||||
int i, j;
|
if (word_size <= 0 || word_size > INT_MAX / 2) {
|
||||||
for (i = 0, j = 0; i < l; i++, j++) {
|
hyphword[0] = '\0';
|
||||||
if (hyphens[i]&1) {
|
return;
|
||||||
hyphword[j] = word[i];
|
}
|
||||||
if (*rep && *pos && *cut && (*rep)[i]) {
|
|
||||||
size_t offset = j - (*pos)[i] + 1;
|
/* hyphword buffer size must be at least 2 * l */
|
||||||
strncpy(hyphword + offset, (*rep)[i], hyphenslen - offset - 1);
|
int hyphword_size = 2 * word_size - 1;
|
||||||
hyphword[hyphenslen-1] = '\0';
|
|
||||||
j += strlen((*rep)[i]) - (*pos)[i];
|
int nonstandard = 0;
|
||||||
|
if (*rep && *pos && *cut) {
|
||||||
|
nonstandard = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int j = 0;
|
||||||
|
for (i = 0; i < word_size && j < hyphword_size; i++) {
|
||||||
|
hyphword[j++] = word[i];
|
||||||
|
if (hyphens[i]&1 && j < hyphword_size) {
|
||||||
|
if (nonstandard && (*rep)[i] && j >= (*pos)[i]) {
|
||||||
|
/* non-standard */
|
||||||
|
j -= (*pos)[i];
|
||||||
|
char *s = (*rep)[i];
|
||||||
|
while (*s && j < hyphword_size) {
|
||||||
|
hyphword[j++] = *s++;
|
||||||
|
}
|
||||||
i += (*cut)[i] - (*pos)[i];
|
i += (*cut)[i] - (*pos)[i];
|
||||||
} else hyphword[++j] = '=';
|
} else {
|
||||||
} else hyphword[j] = word[i];
|
/* standard */
|
||||||
|
hyphword[j++] = '=';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hyphword[j] = '\0';
|
hyphword[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ alt3.test \
|
||||||
alt4.test \
|
alt4.test \
|
||||||
alt5.test \
|
alt5.test \
|
||||||
alt6.test \
|
alt6.test \
|
||||||
|
alt7.test \
|
||||||
compound.test \
|
compound.test \
|
||||||
compound2.test \
|
compound2.test \
|
||||||
compound3.test \
|
compound3.test \
|
||||||
|
@ -46,6 +47,9 @@ alt5.word \
|
||||||
alt6.hyph \
|
alt6.hyph \
|
||||||
alt6.pat \
|
alt6.pat \
|
||||||
alt6.word \
|
alt6.word \
|
||||||
|
alt7.hyph \
|
||||||
|
alt7.pat \
|
||||||
|
alt7.word \
|
||||||
alt.hyph \
|
alt.hyph \
|
||||||
alt.pat \
|
alt.pat \
|
||||||
alt.word \
|
alt.word \
|
||||||
|
@ -100,6 +104,7 @@ alt3.test \
|
||||||
alt4.test \
|
alt4.test \
|
||||||
alt5.test \
|
alt5.test \
|
||||||
alt6.test \
|
alt6.test \
|
||||||
|
alt7.test \
|
||||||
alt.test \
|
alt.test \
|
||||||
basealt2.test \
|
basealt2.test \
|
||||||
basealt.test \
|
basealt.test \
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
b=bbbbbbbbbbbbbbbbbbbbbba=a=a=a=a=a=a=a=a=a=a=a=a=a=a=a
|
||||||
|
b=bbbbbbbbbbbbbbbbbbbbbba=b=bbbbbbbbbbbbbbbbbbbbbba=b=b
|
|
@ -0,0 +1,7 @@
|
||||||
|
ISO8859-1
|
||||||
|
LEFTHYPHENMIN 1
|
||||||
|
RIGHTHYPHENMIN 1
|
||||||
|
% Check for buffer overflows
|
||||||
|
.a1b.
|
||||||
|
a9a
|
||||||
|
ab3a/b=bbbbbbbbbbbbbbbbbbbbbb,1,2
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
DIR="`dirname $0`"
|
||||||
|
NAME="`basename $0 .test`"
|
||||||
|
$DIR/test.sh $NAME.pat $NAME.word $NAME.hyph
|
|
@ -0,0 +1,2 @@
|
||||||
|
abaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
abaabaababababababababababab
|
Loading…
Reference in New Issue