forked from github/server
Merge pull request #784 from ennorehling/develop
fix str_escape read overflow
This commit is contained in:
commit
82f2aa0d52
2 changed files with 25 additions and 2 deletions
|
@ -312,10 +312,13 @@ char *str_unescape(char *str) {
|
||||||
|
|
||||||
const char *str_escape_ex(const char *str, char *buffer, size_t size, const char *chars)
|
const char *str_escape_ex(const char *str, char *buffer, size_t size, const char *chars)
|
||||||
{
|
{
|
||||||
|
size_t slen = strlen(str);
|
||||||
const char *read = str;
|
const char *read = str;
|
||||||
char *write = buffer;
|
char *write = buffer;
|
||||||
if (size < 1) return NULL;
|
if (size < 1) {
|
||||||
while (size > 1 && *read) {
|
return NULL;
|
||||||
|
}
|
||||||
|
while (slen > 0 && size > 1 && *read) {
|
||||||
const char *pos = strpbrk(read, chars);
|
const char *pos = strpbrk(read, chars);
|
||||||
size_t len = size;
|
size_t len = size;
|
||||||
if (pos) {
|
if (pos) {
|
||||||
|
@ -324,7 +327,11 @@ const char *str_escape_ex(const char *str, char *buffer, size_t size, const char
|
||||||
if (len < size) {
|
if (len < size) {
|
||||||
unsigned char ch = *(const unsigned char *)pos;
|
unsigned char ch = *(const unsigned char *)pos;
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
if (len > slen) {
|
||||||
|
len = slen;
|
||||||
|
}
|
||||||
memmove(write, read, len);
|
memmove(write, read, len);
|
||||||
|
slen -= len;
|
||||||
write += len;
|
write += len;
|
||||||
read += len;
|
read += len;
|
||||||
size -= len;
|
size -= len;
|
||||||
|
@ -376,13 +383,18 @@ const char *str_escape_ex(const char *str, char *buffer, size_t size, const char
|
||||||
else size = 1;
|
else size = 1;
|
||||||
}
|
}
|
||||||
++read;
|
++read;
|
||||||
|
--slen;
|
||||||
} else {
|
} else {
|
||||||
/* end of buffer space */
|
/* end of buffer space */
|
||||||
len = size - 1;
|
len = size - 1;
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
if (len > slen) {
|
||||||
|
len = slen;
|
||||||
|
}
|
||||||
memmove(write, read, len);
|
memmove(write, read, len);
|
||||||
write += len;
|
write += len;
|
||||||
size -= len;
|
size -= len;
|
||||||
|
slen -= len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,16 @@ static void test_str_unescape(CuTest * tc)
|
||||||
CuAssertStrEquals(tc, "\"\\\n\t\ra", scratch);
|
CuAssertStrEquals(tc, "\"\\\n\t\ra", scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_str_escape_ex(CuTest * tc)
|
||||||
|
{
|
||||||
|
char scratch[16];
|
||||||
|
|
||||||
|
CuAssertPtrEquals(tc, NULL, (void *)str_escape_ex("1234", scratch, 0, "\\\""));
|
||||||
|
memset(scratch, 0, sizeof(scratch));
|
||||||
|
CuAssertStrEquals(tc, "1234", (void *)str_escape_ex("1234\000abcd", scratch, 16, "\\\""));
|
||||||
|
CuAssertIntEquals(tc, 0, scratch[5]);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_str_escape(CuTest * tc)
|
static void test_str_escape(CuTest * tc)
|
||||||
{
|
{
|
||||||
char scratch[16];
|
char scratch[16];
|
||||||
|
@ -149,6 +159,7 @@ CuSuite *get_strings_suite(void)
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_str_hash);
|
SUITE_ADD_TEST(suite, test_str_hash);
|
||||||
SUITE_ADD_TEST(suite, test_str_escape);
|
SUITE_ADD_TEST(suite, test_str_escape);
|
||||||
|
SUITE_ADD_TEST(suite, test_str_escape_ex);
|
||||||
SUITE_ADD_TEST(suite, test_str_unescape);
|
SUITE_ADD_TEST(suite, test_str_unescape);
|
||||||
SUITE_ADD_TEST(suite, test_str_replace);
|
SUITE_ADD_TEST(suite, test_str_replace);
|
||||||
SUITE_ADD_TEST(suite, test_str_slprintf);
|
SUITE_ADD_TEST(suite, test_str_slprintf);
|
||||||
|
|
Loading…
Reference in a new issue