diff options
author | Luis Ontanon <luis.ontanon@gmail.com> | 2007-04-01 14:55:25 +0000 |
---|---|---|
committer | Luis Ontanon <luis.ontanon@gmail.com> | 2007-04-01 14:55:25 +0000 |
commit | b2e5988e63c7a7f75ed0c21f465abdad81ab49ea (patch) | |
tree | f5edd4535bf947cace94168acb9c473c01c08bee /epan | |
parent | 0e34913ca883483d3f9a470a9a85aa84792f6bfd (diff) |
Fix management of lstrings in uat code so that arbitrary chars (even '\0's) can be used inside.
Fixes bug 1502
svn path=/trunk/; revision=21294
Diffstat (limited to 'epan')
-rw-r--r-- | epan/uat-int.h | 4 | ||||
-rw-r--r-- | epan/uat.c | 152 | ||||
-rw-r--r-- | epan/uat.h | 6 | ||||
-rw-r--r-- | epan/uat_load.l | 140 |
4 files changed, 161 insertions, 141 deletions
diff --git a/epan/uat-int.h b/epan/uat-int.h index 5bf22be9dc..45485e979c 100644 --- a/epan/uat-int.h +++ b/epan/uat-int.h @@ -87,6 +87,10 @@ gboolean uat_load(uat_t* , char** ); void uat_load_all(void); +char* uat_undquote(const char* si, guint in_len, guint* len_p); +char* uat_unbinstring(const char* si, guint in_len, guint* len_p); +char* uat_esc(const char* buf, guint len); + #define UAT_UPDATE(uat) do { *((uat)->user_ptr) = (void*)((uat)->user_data->data); *((uat)->nrows_p) = (uat)->user_data->len; } while(0) #define UAT_INDEX_PTR(uat,idx) (uat->user_data->data + (uat->record_size * (idx))) #endif diff --git a/epan/uat.c b/epan/uat.c index fcf01eb038..0dbdedb092 100644 --- a/epan/uat.c +++ b/epan/uat.c @@ -388,6 +388,158 @@ gboolean uat_fld_chk_enum(void* u1 _U_, const char* strptr, unsigned len, void* return FALSE; } +static int xton(char d) { + switch(d) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + default: return -1; + } +} + +char* uat_unbinstring(const char* si, guint in_len, guint* len_p) { + guint8* buf; + guint len = in_len/2; + int i = 0; + + if (in_len%2) { + return NULL; + } + + buf= g_malloc(len); + *len_p = len; + + while(in_len) { + int d1 = xton(*(si++)); + int d0 = xton(*(si++)); + + buf[i++] = (d1 * 16) + d0; + + in_len -= 2; + } + + return (void*)buf; +} + +char* uat_unesc(const char* si, guint in_len, guint* len_p) { + char* buf = g_malloc0(in_len); + char* p = buf; + guint len = 0; + const char* s; + const char* in_end = si+in_len; + + for (s = (void*)si; s < in_end; s++) { + switch(*s) { + case '\\': + switch(*(++s)) { + case 'a': *(p++) = '\a'; len++; break; + case 'b': *(p++) = '\b'; len++; break; + case 'e': *(p++) = '\033' /* '\e' is non ANSI-C */; len++; printf("."); break; + case 'f': *(p++) = '\f'; len++; break; + case 'n': *(p++) = '\n'; len++; break; + case 'r': *(p++) = '\r'; len++; break; + case 't': *(p++) = '\t'; len++; break; + case 'v': *(p++) = '\v'; len++; break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int c0 = 0; + int c1 = 0; + int c2 = 0; + int c = 0; + + c0 = (*s) - '0'; + + if ( s[1] >= '0' && s[1] <= '7' ) { + c1 = c0; + c0 = (*++s) - '0'; + + if ( s[1] >= '0' && s[1] <= '7' ) { + c2 = c1; + c1 = c0; + c0 = (*++s) - '0'; + } + } + c = (64 * c2) + (8 * c1) + c0; + *(p++) = (char) (c > 255 ? 255 : c); + len++; + break; + } + + case 'x': + { + char c1 = *(s+1); + char c0 = *(s+2); + + if (isxdigit(c1) && isxdigit(c0)) { + *(p++) = (xton(c1) * 0x10) + xton(c0); + s += 2; + } else { + *(p++) = *s; + } + len++; + break; + } + default: + *p++ = *s; + break; + } + break; + default: + *(p++) = *s; + len++; + break; + } + } + + if (len_p) *len_p = len; + return buf; +} + +char* uat_undquote(const char* si, guint in_len, guint* len_p) { + return uat_unesc(si+1,in_len-2,len_p); +} + + +char* uat_esc(const char* buf, guint len) { + const guint8* end = ((guint8*)buf)+len; + char* out = ep_alloc0((4*len)+1); + const guint8* b; + char* s = out; + + for (b = (void*)buf; b < end; b++) { + if (isprint(*b) ) { + *(s++) = (*b); + } else { + g_snprintf(s,5,"\\x%.2x",((guint)*b)); + s+=4; + } + } + + return out; + +} + CHK_STR_IS_DEF(isprint) CHK_STR_IS_DEF(isalpha) CHK_STR_IS_DEF(isalnum) diff --git a/epan/uat.h b/epan/uat.h index c950e7fae6..65afbb06d4 100644 --- a/epan/uat.h +++ b/epan/uat.h @@ -318,11 +318,11 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, #define UAT_LSTRING_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \ static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\ if ((((rec_t*)rec)->ptr_element)) g_free((((rec_t*)rec)->ptr_element)); \ - (((rec_t*)rec)->ptr_element) = g_strndup(buf,len); \ - (((rec_t*)rec)->len_element) = len; } \ + (((rec_t*)rec)->ptr_element) = uat_unesc(buf,len,&(((rec_t*)rec)->len_element)); }\ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\ if (((rec_t*)rec)->ptr_element ) { \ - *out_ptr = (((rec_t*)rec)->ptr_element); *out_len = (((rec_t*)rec)->len_element); \ + *out_ptr = uat_esc(((rec_t*)rec)->ptr_element, (((rec_t*)rec)->len_element)); \ + *out_len = strlen(*out_ptr); \ } else { \ *out_ptr = ""; *out_len = 0; } } diff --git a/epan/uat_load.l b/epan/uat_load.l index d467d3810e..86c1eec758 100644 --- a/epan/uat_load.l +++ b/epan/uat_load.l @@ -56,9 +56,6 @@ static void* record; static guint linenum; - static char* unbinstring(const char* si, guint in_len, guint* len_p); - static char* undquote(const char* si, guint in_len, guint* len_p); - #define ERROR(fmtd) do { error = ep_strdup_printf("%s:%d: %s",uat->filename,linenum,ep_strdup_printf fmtd); yyterminate(); } while(0) #define SET_FIELD() \ @@ -127,7 +124,7 @@ comment #[^\n]*\n } <START_OF_LINE,NEXT_FIELD>{quoted_string} { - ptr = undquote(yytext,yyleng,&len); + ptr = uat_undquote(yytext,yyleng,&len); if (colnum < uat->ncols - 1) { @@ -140,7 +137,7 @@ comment #[^\n]*\n } <START_OF_LINE,NEXT_FIELD>{binstring} { - ptr = unbinstring(yytext,yyleng,&len); + ptr = uat_unbinstring(yytext,yyleng,&len); if (!ptr) { ERROR(("uneven hexstring for field %s",uat->fields[colnum].name)); @@ -224,141 +221,8 @@ comment #[^\n]*\n %% -static int xton(char d) { - switch(d) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: return -1; - } -} -static char* unbinstring(const char* si, guint in_len, guint* len_p) { - guint8* buf; - guint len = in_len/2; - int i = 0; - - if (in_len%2) { - return NULL; - } - - buf= g_malloc(len); - *len_p = len; - - while(in_len) { - int d1 = xton(*(si++)); - int d0 = xton(*(si++)); - - buf[i++] = (d1 * 16) + d0; - - in_len -= 2; - } - - return (void*)buf; -} -static char* undquote(const char* si, guint in_len, guint* len_p) { - char* buf = g_malloc(in_len); /* wastes one byte for every '\\' in text */ - char* p = buf; - guint len = 0; - char* end = buf+in_len; - const guint8* s = (void*)si; - - for (s++; p < end; s++) { - switch(*s) { - case '\0': - *(p-1) = '\0'; - goto done; - case '\\': - switch(*(++s)) { - case 'a': *(p++) = '\a'; len++; break; - case 'b': *(p++) = '\b'; len++; break; - case 'e': *(p++) = '\033' /* '\e' is non ANSI-C */; len++; break; - case 'f': *(p++) = '\f'; len++; break; - case 'n': *(p++) = '\n'; len++; break; - case 'r': *(p++) = '\r'; len++; break; - case 't': *(p++) = '\t'; len++; break; - case 'v': *(p++) = '\v'; len++; break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int c0 = 0; - int c1 = 0; - int c2 = 0; - int c = 0; - - c0 = (*s) - '0'; - - if ( s[1] >= '0' && s[1] <= '7' ) { - c1 = c0; - c0 = (*++s) - '0'; - - if ( s[1] >= '0' && s[1] <= '7' ) { - c2 = c1; - c1 = c0; - c0 = (*++s) - '0'; - } - } - c = (64 * c2) + (8 * c1) + c0; - *(p++) = (char) (c > 255 ? 255 : c); - len++; - break; - } - - case 'x': - { - char c1 = *(s+1); - char c0 = *(s+2); - - if (isxdigit(c1) && isxdigit(c0)) { - *(p++) = (xton(c1) * 0x10) + xton(c0); - s += 2; - } else { - *(p++) = *s; - } - len++; - break; - } - default: - *p++ = *s; - break; - } - break; - default: - *(p++) = *s; - len++; - break; - } - } - -done: - - while ( p < end ) *(p++) = '\0'; - buf[len] = '\0'; - len--; - if (len_p) *len_p = len; - return buf; -} gboolean uat_load(uat_t* uat_in, char** err) { gchar* fname = uat_get_actual_filename(uat_in, FALSE); |