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