--- parser3/src/main/untaint.C 2001/08/28 10:30:28 1.60 +++ parser3/src/main/untaint.C 2001/10/29 16:56:31 1.72 @@ -2,10 +2,10 @@ Parser: String class part: untaint mechanizm. Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com) - Author: Alexander Petrosyan (http://design.ru/paf) + + $Id: untaint.C,v 1.72 2001/10/29 16:56:31 paf Exp $ */ -static const char *RCSId="$Id: untaint.C,v 1.60 2001/08/28 10:30:28 parser Exp $"; #include "pa_pool.h" #include "pa_string.h" @@ -15,6 +15,7 @@ static const char *RCSId="$Id: untaint.C #include "pa_globals.h" #include "pa_sql_connection.h" #include "pa_dictionary.h" +#include "pa_common.h" #define escape(action) \ { \ @@ -75,13 +76,14 @@ static const char * String_Untaint_lang_ just a flag, that value not stored */ "A", ///< leave all characters intact - "F", ///< filename - "H", ///< text in HTTP response header + "F", ///< file specification + "H", ///< ext in HTTP response header "M", ///< text in mail header "URI", ///< text in uri "T", ///< ^table:set body "SQL", ///< ^table:sql body "JS", ///< JavaScript code + "XML", ///< ^dom:set xml "HTML", ///< HTML code (for editing) "UHTML", ///< HTML code with USER chars }; @@ -146,7 +148,15 @@ inline bool need_quote_http_header(const @todo fix potential forigins_mode buf overrun */ size_t String::cstr_bufsize(Untaint_lang lang) const { - return (lang==UL_AS_IS?size():size()*UNTAINT_TIMES_BIGGER*(forigins_mode?10:1)) +1; + return ( + lang==UL_AS_IS? + size() + : + size() + *UNTAINT_TIMES_BIGGER + *(forigins_mode?10:1) + ) + +1; } /** @todo fix theoretical \n mem overrun in TYPO replacements @@ -162,11 +172,11 @@ char *String::store_to(char *dest, Untai const Chunk *chunk=&head; do { const Chunk::Row *row=chunk->rows; - for(size_t i=0; icount; i++, row++) { + for(uint i=0; icount; i++, row++) { if(row==append_here) goto break2; - Untaint_lang to_lang=lang==UL_UNSPECIFIED?row->item.lang:lang; + Untaint_lang to_lang=lang==UL_UNSPECIFIED?(Untaint_lang)row->item.lang:lang; char *dest_before_origins=dest; @@ -193,12 +203,12 @@ char *String::store_to(char *dest, Untai const char *src=row->item.ptr; for(int size=row->item.size; size--; src++) switch(*src) { - case ' ': case '\n': case '\r': case '\t': + /***case ' ': case '\n': case '\t': if(!whitespace) { *dest++=*src; whitespace=true; } - break; + break;*/ default: whitespace=false; *dest++=*src; @@ -215,7 +225,7 @@ char *String::store_to(char *dest, Untai memcpy(dest, row->item.ptr, row->item.size); dest+=row->item.size; break; - case UL_FILE_NAME: + case UL_FILE_SPEC: // tainted, untaint language: file [name] escape(switch(*src) { case ' ': to_char('_'); break; @@ -230,18 +240,11 @@ char *String::store_to(char *dest, Untai }); break; case UL_HTTP_HEADER: - // tainted, untaint language: http-header - if(need_quote_http_header(row->item.ptr, row->item.size)) { - *dest++='\"'; - escape(switch(*src) { - case '\"': to_string("\\\"", 2); break; - _default; - }); - *dest++='\"'; - } else { - memcpy(dest, row->item.ptr, row->item.size); - dest+=row->item.size; - } + // tainted, untaint language: http-field-content-text + escape(switch(*src) { + case ' ': to_char('+'); break; + encode(need_uri_encode, '%'); + }); break; case UL_MAIL_HEADER: // tainted, untaint language: mail-header @@ -280,7 +283,7 @@ char *String::store_to(char *dest, Untai if(connection) dest+=connection->quote(dest, row->item.ptr, row->item.size); else - THROW(0, 0, + throw Exception(0, 0, this, "untaint in SQL language failed - no connection specified"); break; @@ -294,25 +297,34 @@ char *String::store_to(char *dest, Untai _default; }); break; + case UL_XML: + escape(switch(*src) { + case '&': to_string("&", 5); break; + case '>': to_string(">", 4); break; + case '<': to_string("<", 4); break; + case '"': to_string(""", 6); break; + case '\'': to_string("'", 6); break; + _default; + }); + break; case UL_HTML: escape(switch(*src) { case '&': to_string("&", 5); break; case '>': to_string(">", 4); break; case '<': to_string("<", 4); break; case '"': to_string(""", 6); break; - //TODO: XSLT case '\'': to_string("'", 6); break; _default; }); break; case UL_USER_HTML: { // tainted, untaint language: html-typo if(!typo_dict) // never, always has default - THROW(0, 0, + throw Exception(0, 0, this, "untaint to user-html lang failed, no typo table"); char *html_for_typo= - (char *)malloc(row->item.size*2/* '\n' -> '\' 'n' */+1); + (char *)malloc(row->item.size*2/* '\n' -> '\' 'n' */+1,16); // note: // there still is a possibility that user // would not replace \n as she supposed to @@ -324,16 +336,9 @@ char *String::store_to(char *dest, Untai char *dest=html_for_typo; escape(switch(*src) { // convinient name for typo match "\n" - case '\r': - to_string("\\n", 2); // \r -> "\n" - if(size && src[1]=='\n') { // \r\n -> remove \n - size--; src++; - } - break; case '\n': to_string("\\n", 2); break; - //TODO: XSLT case '\'': to_string("'", 6); break; _default; }); *dest=0; @@ -351,7 +356,7 @@ char *String::store_to(char *dest, Untai // b allowed to be max UNTAINT_TIMES_BIGGER then a if(b.size()>UNTAINT_TIMES_BIGGER*a.size()) { pool().set_tag(0); // avoid recursion - THROW(0, 0, + throw Exception(0, 0, &b, "is %g times longer then '%s', " "while maximum, handled by Parser, is %d", @@ -372,7 +377,7 @@ char *String::store_to(char *dest, Untai break; } default: - THROW(0, 0, + throw Exception(0, 0, this, "unknown untaint language #%d of %d piece", static_cast(row->item.lang), @@ -387,15 +392,14 @@ char *String::store_to(char *dest, Untai if(dest==dest_after_origins) // never moved==optimized space dest=dest_before_origins; else { - for(char *p=dest_after_origins; plink; } while(chunk); + break2: return dest; }