strescape.c (dovecot-2.3.16) | : | strescape.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 106 | skipping to change at line 106 | |||
if (*p != '"') | if (*p != '"') | |||
return -1; | return -1; | |||
escaped = p_strdup_until(unsafe_data_stack_pool, *str, p); | escaped = p_strdup_until(unsafe_data_stack_pool, *str, p); | |||
*str = p+1; | *str = p+1; | |||
*unescaped_r = !esc_found ? escaped : str_unescape(escaped); | *unescaped_r = !esc_found ? escaped : str_unescape(escaped); | |||
return 0; | return 0; | |||
} | } | |||
void str_append_tabescaped_n(string_t *dest, const unsigned char *src, size_t sr c_size) | void str_append_tabescaped_n(string_t *dest, const unsigned char *src, size_t sr c_size) | |||
{ | { | |||
size_t prev_pos = 0; | ||||
char esc[2] = { '\001', '\0' }; | ||||
for (size_t i = 0; i < src_size; i++) { | for (size_t i = 0; i < src_size; i++) { | |||
switch (src[i]) { | switch (src[i]) { | |||
case '\000': | case '\000': | |||
str_append_c(dest, '\001'); | esc[1] = '0'; | |||
str_append_c(dest, '0'); | ||||
break; | break; | |||
case '\001': | case '\001': | |||
str_append_c(dest, '\001'); | esc[1] = '1'; | |||
str_append_c(dest, '1'); | ||||
break; | break; | |||
case '\t': | case '\t': | |||
str_append_c(dest, '\001'); | esc[1] = 't'; | |||
str_append_c(dest, 't'); | ||||
break; | break; | |||
case '\r': | case '\r': | |||
str_append_c(dest, '\001'); | esc[1] = 'r'; | |||
str_append_c(dest, 'r'); | ||||
break; | break; | |||
case '\n': | case '\n': | |||
str_append_c(dest, '\001'); | esc[1] = 'n'; | |||
str_append_c(dest, 'n'); | ||||
break; | break; | |||
default: | default: | |||
str_append_c(dest, src[i]); | continue; | |||
break; | ||||
} | } | |||
str_append_data(dest, src + prev_pos, i - prev_pos); | ||||
str_append_data(dest, esc, 2); | ||||
prev_pos = i + 1; | ||||
} | } | |||
str_append_data(dest, src + prev_pos, src_size - prev_pos); | ||||
} | } | |||
void str_append_tabescaped(string_t *dest, const char *src) | void str_append_tabescaped(string_t *dest, const char *src) | |||
{ | { | |||
str_append_tabescaped_n(dest, (const unsigned char*)src, strlen(src)); | size_t pos, prev_pos = 0; | |||
char esc[2] = { '\001', '\0' }; | ||||
for (;;) { | ||||
pos = prev_pos + strcspn(src + prev_pos, "\001\t\r\n"); | ||||
str_append_data(dest, src + prev_pos, pos - prev_pos); | ||||
prev_pos = pos + 1; | ||||
switch (src[pos]) { | ||||
case '\000': | ||||
/* end of src string reached */ | ||||
return; | ||||
case '\001': | ||||
esc[1] = '1'; | ||||
break; | ||||
case '\t': | ||||
esc[1] = 't'; | ||||
break; | ||||
case '\r': | ||||
esc[1] = 'r'; | ||||
break; | ||||
case '\n': | ||||
esc[1] = 'n'; | ||||
break; | ||||
default: | ||||
i_unreached(); | ||||
} | ||||
str_append_data(dest, esc, 2); | ||||
} | ||||
} | } | |||
const char *str_tabescape(const char *str) | const char *str_tabescape(const char *str) | |||
{ | { | |||
string_t *tmp; | string_t *tmp; | |||
const char *p; | const char *p; | |||
for (p = str; *p != '\0'; p++) { | if ((p = strpbrk(str, "\001\t\r\n")) != NULL) { | |||
if (*p <= '\r') { | tmp = t_str_new(128); | |||
tmp = t_str_new(128); | str_append_data(tmp, str, p-str); | |||
str_append_data(tmp, str, p-str); | str_append_tabescaped(tmp, p); | |||
str_append_tabescaped(tmp, p); | return str_c(tmp); | |||
return str_c(tmp); | ||||
} | ||||
} | } | |||
return str; | return str; | |||
} | } | |||
void str_append_tabunescaped(string_t *dest, const void *src, size_t src_size) | void str_append_tabunescaped(string_t *dest, const void *src, size_t src_size) | |||
{ | { | |||
const unsigned char *src_c = src; | const unsigned char *src_c = src; | |||
size_t start = 0, i = 0; | size_t start = 0, i = 0; | |||
while (i < src_size) { | while (i < src_size) { | |||
skipping to change at line 199 | skipping to change at line 226 | |||
str_append_c(dest, src_c[i]); | str_append_c(dest, src_c[i]); | |||
break; | break; | |||
} | } | |||
i++; | i++; | |||
} | } | |||
} | } | |||
start = i; | start = i; | |||
} | } | |||
} | } | |||
char *str_tabunescape(char *str) | static char *str_tabunescape_from(char *str, char *src) | |||
{ | { | |||
/* @UNSAFE */ | /* @UNSAFE */ | |||
char *dest, *start = str; | char *dest, *p; | |||
str = strchr(str, '\001'); | dest = src; | |||
if (str == NULL) { | for (;;) { | |||
/* no unescaping needed */ | switch (src[1]) { | |||
return start; | case '\0': | |||
} | /* truncated input */ | |||
*dest = '\0'; | ||||
return str; | ||||
case '0': | ||||
*dest++ = '\000'; | ||||
break; | ||||
case '1': | ||||
*dest++ = '\001'; | ||||
break; | ||||
case 't': | ||||
*dest++ = '\t'; | ||||
break; | ||||
case 'r': | ||||
*dest++ = '\r'; | ||||
break; | ||||
case 'n': | ||||
*dest++ = '\n'; | ||||
break; | ||||
default: | ||||
*dest++ = src[1]; | ||||
break; | ||||
} | ||||
src += 2; | ||||
for (dest = str; *str != '\0'; str++) { | p = strchr(src, '\001'); | |||
if (*str != '\001') | if (p == NULL) { | |||
*dest++ = *str; | memmove(dest, src, strlen(src)+1); | |||
else { | break; | |||
str++; | ||||
if (*str == '\0') | ||||
break; | ||||
switch (*str) { | ||||
case '0': | ||||
*dest++ = '\000'; | ||||
break; | ||||
case '1': | ||||
*dest++ = '\001'; | ||||
break; | ||||
case 't': | ||||
*dest++ = '\t'; | ||||
break; | ||||
case 'r': | ||||
*dest++ = '\r'; | ||||
break; | ||||
case 'n': | ||||
*dest++ = '\n'; | ||||
break; | ||||
default: | ||||
*dest++ = *str; | ||||
break; | ||||
} | ||||
} | } | |||
size_t copy_len = p - src; | ||||
memmove(dest, src, copy_len); | ||||
dest += copy_len; | ||||
src = p; | ||||
} | } | |||
return str; | ||||
} | ||||
*dest = '\0'; | char *str_tabunescape(char *str) | |||
return start; | { | |||
char *src = strchr(str, '\001'); | ||||
if (src == NULL) { | ||||
/* no unescaping needed */ | ||||
return str; | ||||
} | ||||
return str_tabunescape_from(str, src); | ||||
} | } | |||
const char *t_str_tabunescape(const char *str) | const char *t_str_tabunescape(const char *str) | |||
{ | { | |||
if (strchr(str, '\001') == NULL) | const char *p; | |||
p = strchr(str, '\001'); | ||||
if (p == NULL) | ||||
return str; | return str; | |||
else | ||||
return str_tabunescape(t_strdup_noconst(str)); | char *dest = t_strdup_noconst(str); | |||
return str_tabunescape_from(dest, dest + (p - str)); | ||||
} | } | |||
const char *const *t_strsplit_tabescaped_inplace(char *data) | static char **p_strsplit_tabescaped_inplace(pool_t pool, char *data) | |||
{ | { | |||
/* @UNSAFE */ | /* @UNSAFE */ | |||
char **array; | char **array; | |||
unsigned int count, new_alloc_count, alloc_count; | unsigned int count, new_alloc_count, alloc_count; | |||
if (*data == '\0') | if (*data == '\0') | |||
return t_new(const char *, 1); | return p_new(pool, char *, 1); | |||
alloc_count = 32; | alloc_count = 32; | |||
array = t_malloc_no0(sizeof(char *) * alloc_count); | array = pool == unsafe_data_stack_pool ? | |||
t_malloc_no0(sizeof(char *) * alloc_count) : | ||||
p_malloc(pool, sizeof(char *) * alloc_count); | ||||
array[0] = data; count = 1; | array[0] = data; count = 1; | |||
bool need_unescape = FALSE; | char *need_unescape = NULL; | |||
while ((data = strpbrk(data, "\t\001")) != NULL) { | while ((data = strpbrk(data, "\t\001")) != NULL) { | |||
/* separator or escape char found */ | /* separator or escape char found */ | |||
if (*data == '\001') { | if (*data == '\001') { | |||
need_unescape = TRUE; | if (need_unescape == NULL) | |||
need_unescape = data; | ||||
data++; | data++; | |||
continue; | continue; | |||
} | } | |||
if (count+1 >= alloc_count) { | if (count+1 >= alloc_count) { | |||
new_alloc_count = nearest_power(alloc_count+1); | new_alloc_count = nearest_power(alloc_count+1); | |||
array = p_realloc(unsafe_data_stack_pool, array, | array = p_realloc(pool, array, | |||
sizeof(char *) * alloc_count, | sizeof(char *) * alloc_count, | |||
sizeof(char *) * | sizeof(char *) * | |||
new_alloc_count); | new_alloc_count); | |||
alloc_count = new_alloc_count; | alloc_count = new_alloc_count; | |||
} | } | |||
*data++ = '\0'; | *data++ = '\0'; | |||
if (need_unescape) { | if (need_unescape != NULL) { | |||
str_tabunescape(array[count-1]); | str_tabunescape_from(array[count-1], need_unescape); | |||
need_unescape = FALSE; | need_unescape = NULL; | |||
} | } | |||
array[count++] = data; | array[count++] = data; | |||
} | } | |||
if (need_unescape) | if (need_unescape != NULL) | |||
str_tabunescape(array[count-1]); | str_tabunescape_from(array[count-1], need_unescape); | |||
i_assert(count < alloc_count); | i_assert(count < alloc_count); | |||
array[count] = NULL; | array[count] = NULL; | |||
return (const char *const *)array; | return array; | |||
} | } | |||
char **p_strsplit_tabescaped(pool_t pool, const char *str) | const char *const *t_strsplit_tabescaped_inplace(char *data) | |||
{ | { | |||
char **args; | char *const *escaped = | |||
unsigned int i; | p_strsplit_tabescaped_inplace(unsafe_data_stack_pool, data); | |||
return (const char *const *)escaped; | ||||
} | ||||
args = p_strsplit(pool, str, "\t"); | char **p_strsplit_tabescaped(pool_t pool, const char *str) | |||
for (i = 0; args[i] != NULL; i++) | { | |||
args[i] = str_tabunescape(args[i]); | return p_strsplit_tabescaped_inplace(pool, p_strdup(pool, str)); | |||
return args; | ||||
} | } | |||
const char *const *t_strsplit_tabescaped(const char *str) | const char *const *t_strsplit_tabescaped(const char *str) | |||
{ | { | |||
return (void *)p_strsplit_tabescaped(unsafe_data_stack_pool, str); | return t_strsplit_tabescaped_inplace(t_strdup_noconst(str)); | |||
} | } | |||
End of changes. 33 change blocks. | ||||
79 lines changed or deleted | 126 lines changed or added |