Annotation of parser3/src/main/untaint.C, revision 1.10

1.7       paf         1: /** @file
1.8       paf         2:        Parser: String class part: untaint mechanizm.
                      3: 
1.1       paf         4:        Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.8       paf         5: 
1.1       paf         6:        Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
                      7: 
1.10    ! paf         8:        $Id: untaint.C,v 1.9 2001/03/19 20:46:38 paf Exp $
1.1       paf         9: */
                     10: 
                     11: #include <string.h>
                     12: 
                     13: #include "pa_pool.h"
                     14: #include "pa_string.h"
                     15: #include "pa_hash.h"
                     16: #include "pa_exception.h"
                     17: 
                     18: #define escape(cases) \
                     19:        { \
                     20:                const char *ptr=row->item.ptr; \
1.3       paf        21:                for (int size=row->item.size; size--; ptr++) \
1.1       paf        22:                        switch(*ptr) { \
                     23:                                cases \
                     24:                        } \
                     25:        }
1.4       paf        26: #define escape_value(a, c)  case a: *copy_here++=c; break
                     27: #define escape_default  default: *copy_here++=*ptr; break
1.1       paf        28: #define escape_subst(a, b, bsize)  \
1.4       paf        29:                case a: \
1.1       paf        30:                        strncpy(copy_here, b, bsize); \
                     31:                        copy_here+=bsize; \
1.4       paf        32:                break
1.9       paf        33: #define escape_encode(need_encode_func, prefix)  \
1.5       paf        34:                default: \
                     35:                        if(need_encode_func(*ptr)) { \
                     36:                                static const char *hex="0123456789ABCDEF"; \
1.9       paf        37:                                char chunk[3]={prefix}; \
1.5       paf        38:                                chunk[1]=hex[((unsigned char)*ptr)/0x10]; \
                     39:                                chunk[2]=hex[((unsigned char)*ptr)%0x10]; \
                     40:                                strncpy(copy_here, chunk, 3);  copy_here+=3; \
                     41:                        } else \
                     42:                                *copy_here++=*ptr; \
                     43:                        break
1.4       paf        44: 
1.9       paf        45: inline bool need_file_encode(unsigned char c){
                     46:     if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z')) 
                     47:                return false;
                     48: 
                     49:     return !strchr("./\\", c);
                     50: }
1.5       paf        51: inline bool need_uri_encode(unsigned char c){
1.4       paf        52:     if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z')) 
                     53:                return false;
                     54: 
1.5       paf        55:     return !strchr("_-./", c);
                     56: }
                     57: inline bool need_header_encode(unsigned char c){
                     58:     if(strchr(" ,:", c))
                     59:                return false;
                     60: 
                     61:        return need_uri_encode(c);
1.4       paf        62: }
1.1       paf        63: 
                     64: // String
                     65: 
1.9       paf        66: /// @todo optimize whitespaces for all but 'html'
1.1       paf        67: char *String::cstr() const {
1.2       paf        68:        char *result=(char *)malloc(size()*UNTAINT_TIMES_BIGGER+1);
1.1       paf        69: 
                     70:        char *copy_here=result;
                     71:        const Chunk *chunk=&head; 
                     72:        do {
                     73:                const Chunk::Row *row=chunk->rows;
                     74:                for(int i=0; i<chunk->count; i++) {
                     75:                        if(row==append_here)
                     76:                                goto break2;
                     77: 
                     78:                        // WARNING:
                     79:                        //      string can grow only UNTAINT_TIMES_BIGGER
                     80:                        switch(row->item.lang) {
                     81:                        case NO:
                     82:                                // clean piece
                     83:                        case YES:
                     84:                                // tainted piece, but undefined untaint language
                     85:                                // for VString.get_double of tainted values
                     86:                                // for ^process{body} evaluation
                     87:                        case AS_IS:
                     88:                                // tainted, untaint language: as-is
                     89:                                memcpy(copy_here, row->item.ptr, row->item.size); 
                     90:                                copy_here+=row->item.size;
                     91:                                break;
1.10    ! paf        92:                        case FILE_NAME:
1.9       paf        93:                                // tainted, untaint language: file [name]
                     94:                                escape(
                     95:                                        escape_value(' ', '_');
                     96:                                        escape_encode(need_file_encode, '-');
                     97:                                );
                     98:                                break;
1.4       paf        99:                        case URI:
                    100:                                // tainted, untaint language: uri
                    101:                                escape(
                    102:                                        escape_value(' ', '+');
1.9       paf       103:                                        escape_encode(need_uri_encode, '%');
1.5       paf       104:                                );
                    105:                                break;
                    106:                        case HEADER:
                    107:                                // tainted, untaint language: header
                    108:                                escape(
1.9       paf       109:                                        escape_encode(need_header_encode, '%');
1.4       paf       110:                                );
                    111:                                break;
1.1       paf       112:                        case TABLE: 
                    113:                                escape(
1.4       paf       114:                                        escape_value('\t', ' ');
                    115:                                        escape_value('\n', ' ');
                    116:                                        escape_default;
1.1       paf       117:                                );
                    118:                                break;
                    119:                        case SQL:
                    120:                                // tainted, untaint language: sql
                    121:                                // TODO: зависимость от sql сервера
                    122:                                memset(copy_here, '?', row->item.size); 
                    123:                                copy_here+=row->item.size;
                    124:                                break;
                    125:                        case JS:
                    126:                                escape(
1.4       paf       127:                                        escape_subst('"', "\\\"", 2);
                    128:                                        escape_subst('\'', "\\'", 2);
                    129:                                        escape_subst('\n', "\\n", 2);
                    130:                                        escape_subst('\r', "\\r", 2);
                    131:                                        escape_subst('\\', "\\\\", 2);
                    132:                                        escape_subst('я', "\\я", 2);
                    133:                                        escape_default;
1.1       paf       134:                                );
                    135:                                break;
                    136:                        case HTML:
                    137:                                escape(
1.4       paf       138:                                        escape_subst('&', "&amp;", 5); // BEFORE consequent relpaces yelding '&'
                    139:                                        escape_subst('>', "&gt;", 4);
                    140:                                        escape_subst('<', "&lt;",4);
                    141:                                        escape_subst('"', "&quot;",6);
                    142:                                        escape_value('\t', ' ');
1.1       paf       143:                                        //TODO: XSLT escape_subst('\'', "&apos;", 6)
1.4       paf       144:                                        escape_default;
1.1       paf       145:                                );
                    146:                                break;
                    147:                        case HTML_TYPO: 
                    148:                                // tainted, untaint language: html-typo
                    149:                                escape(
1.4       paf       150:                                        escape_subst('&', "&amp;", 5); // BEFORE consequent relpaces yelding '&'
                    151:                                        escape_subst('>', "&gt;", 4);
                    152:                                        escape_subst('<', "&lt;",4);
                    153:                                        escape_subst('"', "&quot;",6);
                    154:                                        escape_value('\t', ' ');
1.1       paf       155:                                        //TODO: $MAIN:html-type table replace, max length(b)==UNTAINT_TIMES_BIGGER*length(a)
1.4       paf       156:                                        escape_default;
1.1       paf       157:                                );
                    158:                                break;
                    159:                        default:
                    160:                                THROW(0,0,
                    161:                                        this,
                    162:                                        "unknown untaint language #%d of %d piece", 
                    163:                                                static_cast<int>(row->item.lang),
                    164:                                                i);
                    165:                        }
                    166:                        row++;
                    167:                }
                    168:                chunk=row->link;
                    169:        } while(chunk);
                    170: break2:
                    171:        *copy_here=0;
                    172:        return result;
                    173: }

E-mail: