Annotation of parser3/src/main/untaint.C, revision 1.8
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.8 ! paf 8: $Id: untaint.C,v 1.7 2001/03/19 16:44:03 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.5 paf 33: #define escape_encode(need_encode_func) \
34: default: \
35: if(need_encode_func(*ptr)) { \
36: static const char *hex="0123456789ABCDEF"; \
37: char chunk[3]={'%'}; \
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.5 paf 45: inline bool need_uri_encode(unsigned char c){
1.4 paf 46: if ((c>='0') && (c<='9') || (c>='A') && (c<='Z') || (c>='a') && (c<='z'))
47: return false;
48:
1.5 paf 49: return !strchr("_-./", c);
50: }
51: inline bool need_header_encode(unsigned char c){
52: if(strchr(" ,:", c))
53: return false;
54:
55: return need_uri_encode(c);
1.4 paf 56: }
1.1 paf 57:
58: // String
59:
1.6 paf 60: /// \todo optimize whitespaces for all but 'html'
1.1 paf 61: char *String::cstr() const {
1.2 paf 62: char *result=(char *)malloc(size()*UNTAINT_TIMES_BIGGER+1);
1.1 paf 63:
64: char *copy_here=result;
65: const Chunk *chunk=&head;
66: do {
67: const Chunk::Row *row=chunk->rows;
68: for(int i=0; i<chunk->count; i++) {
69: if(row==append_here)
70: goto break2;
71:
72: // WARNING:
73: // string can grow only UNTAINT_TIMES_BIGGER
74: switch(row->item.lang) {
75: case NO:
76: // clean piece
77: case YES:
78: // tainted piece, but undefined untaint language
79: // for VString.get_double of tainted values
80: // for ^process{body} evaluation
81: case AS_IS:
82: // tainted, untaint language: as-is
83: memcpy(copy_here, row->item.ptr, row->item.size);
84: copy_here+=row->item.size;
85: break;
1.4 paf 86: case URI:
87: // tainted, untaint language: uri
88: escape(
89: escape_value(' ', '+');
1.5 paf 90: escape_encode(need_uri_encode);
91: );
92: break;
93: case HEADER:
94: // tainted, untaint language: header
95: escape(
96: escape_encode(need_header_encode);
1.4 paf 97: );
98: break;
1.1 paf 99: case TABLE:
100: escape(
1.4 paf 101: escape_value('\t', ' ');
102: escape_value('\n', ' ');
103: escape_default;
1.1 paf 104: );
105: break;
106: case SQL:
107: // tainted, untaint language: sql
108: // TODO: зависимость от sql сервера
109: memset(copy_here, '?', row->item.size);
110: copy_here+=row->item.size;
111: break;
112: case JS:
113: escape(
1.4 paf 114: escape_subst('"', "\\\"", 2);
115: escape_subst('\'', "\\'", 2);
116: escape_subst('\n', "\\n", 2);
117: escape_subst('\r', "\\r", 2);
118: escape_subst('\\', "\\\\", 2);
119: escape_subst('я', "\\я", 2);
120: escape_default;
1.1 paf 121: );
122: break;
123: case HTML:
124: escape(
1.4 paf 125: escape_subst('&', "&", 5); // BEFORE consequent relpaces yelding '&'
126: escape_subst('>', ">", 4);
127: escape_subst('<', "<",4);
128: escape_subst('"', """,6);
129: escape_value('\t', ' ');
1.1 paf 130: //TODO: XSLT escape_subst('\'', "'", 6)
1.4 paf 131: escape_default;
1.1 paf 132: );
133: break;
134: case HTML_TYPO:
135: // tainted, untaint language: html-typo
136: escape(
1.4 paf 137: escape_subst('&', "&", 5); // BEFORE consequent relpaces yelding '&'
138: escape_subst('>', ">", 4);
139: escape_subst('<', "<",4);
140: escape_subst('"', """,6);
141: escape_value('\t', ' ');
1.1 paf 142: //TODO: $MAIN:html-type table replace, max length(b)==UNTAINT_TIMES_BIGGER*length(a)
1.4 paf 143: escape_default;
1.1 paf 144: );
145: break;
146: default:
147: THROW(0,0,
148: this,
149: "unknown untaint language #%d of %d piece",
150: static_cast<int>(row->item.lang),
151: i);
152: }
153: row++;
154: }
155: chunk=row->link;
156: } while(chunk);
157: break2:
158: *copy_here=0;
159: return result;
160: }
E-mail: