--- parser3/src/main/untaint.C 2004/02/17 10:38:08 1.130 +++ parser3/src/main/untaint.C 2006/02/18 18:01:33 1.136.6.1 @@ -1,11 +1,11 @@ /** @file Parser: String class part: untaint mechanizm. - Copyright(c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com) + Copyright(c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_UNTAINT_C="$Date: 2004/02/17 10:38:08 $"; +static const char * const IDENT_UNTAINT_C="$Date: 2006/02/18 18:01:33 $"; #include "pa_string.h" @@ -34,7 +34,7 @@ extern "C" { // author forgot to do that { \ bool skip=false; \ if(optimize) switch(c) { \ - case ' ': case '\r': case '\n': case '\t': \ + case ' ': case '\n': case '\t': \ if(whitespace) \ skip=true; /*skipping subsequent*/ \ else \ @@ -58,7 +58,7 @@ extern "C" { // author forgot to do that char c=CORD_pos_fetch(info->pos); \ action \ } -#define _default default: CORD_ec_append(info->result, c); break +#define _default CORD_ec_append(info->result, c) #define encode(need_encode_func, prefix, otherwise) \ if(need_encode_func(c)) { \ static const char* hex="0123456789ABCDEF"; \ @@ -92,6 +92,9 @@ inline bool need_http_header_encode(unsi return need_uri_encode(c); } +inline bool need_regex_escape(unsigned char c){ + return strchr("\\^$.[]|()?*+{}", c)!=0; +} // String @@ -371,6 +374,8 @@ int cstr_to_string_body_block(char alang bool email=false; uchar c; for(const char* src=mail_ptr; (c=(uchar)*src++); ) { + if(c=='\r' || c=='\n') + c=' '; if(to_quoted_printable && (c==',' || c == '"' || addr_spec_soon(src-1/*position to 'c'*/))) { email=c=='<'; to_string("?="); @@ -399,14 +404,6 @@ int cstr_to_string_body_block(char alang } else ec_append(info->result, optimize, whitespace, info->pos, fragment_length); break; - case String::L_TABLE: - // tainted, untaint language: table - escape(switch(c) { - case '\t': to_char(' '); break; - case '\n': to_char(' '); break; - _default; - }); - break; case String::L_SQL: // tainted, untaint language: sql if(info->connection) { @@ -427,17 +424,39 @@ int cstr_to_string_body_block(char alang case '\n': to_string("\\n"); break; case '\\': to_string("\\\\"); break; case '\xFF': to_string("\\\xFF"); break; - _default; + default: _default; break; }); break; case String::L_XML: + // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] escape(switch(c) { + case '\x9': + case '\xA': + case '\xD': // this is usually removed on input + _default; + break; case '&': to_string("&"); break; case '>': to_string(">"); break; case '<': to_string("<"); break; case '"': to_string("""); break; case '\'': to_string("'"); break; - _default; + default: + if(((unsigned char)c)<0x20) { + // fixing it, so that libxml would not result + // in fatal error parsing text + // though it really violates standard. + // to indicate there were an error + // replace bad char not to it's code, + // which we can do, + // but rather to '!' to show that input were actually + // invalid. + // life: shows that MSIE can somehow garble form values + // so that they contain these chars. + to_char('!'); + } else { + _default; + } + break; }); break; case String::L_HTML: @@ -446,9 +465,17 @@ int cstr_to_string_body_block(char alang case '>': to_string(">"); break; case '<': to_string("<"); break; case '"': to_string("""); break; - _default; + default: _default; break; }); break; + case String::L_REGEX: + // tainted, untaint language: regex + escape( + if(need_regex_escape(c)) + to_char('\\') + _default; + ); + break; default: SAPI::abort("unknown untaint language #%d", static_cast(to_lang)); // should never @@ -464,6 +491,8 @@ int cstr_to_string_body_block(char alang String::Body String::cstr_to_string_body(Language lang, SQL_Connection* connection, const Request_charsets *charsets) const { + if(is_empty()) + return String::Body(); Cstr_to_string_body_block_info info; // input @@ -478,8 +507,6 @@ String::Body String::cstr_to_string_body info.fragment_begin=0; info.whitespace=true; - if(!is_empty()) - langs.for_each(body, cstr_to_string_body_block, &info); - + langs.for_each(body, cstr_to_string_body_block, &info); return String::Body(CORD_ec_to_cord(info.result)); }