Browse code

core: parse_cseq wrong use of parse_method fix

- parse_method renamed to parse_method_advance(), made static and
changed to check if the method name ends with a non-token char.
- added parse_method_name() for parsing a single method name with
known length (no leading or trailing whitespace).
- changed parse_cseq() to use parse_method_name()
(it's previous use of parse_method() had the side effect of
setting the method name to "").

Reported-by: Henning Westerholt <henning.westerholt@1und1.de>

Andrei Pelinescu-Onciul authored on 20/05/2009 17:06:43
Showing 3 changed files
... ...
@@ -74,8 +74,8 @@ char* parse_cseq(char *buf, char* end, struct cseq_body* cb)
74 74
 	cb->method.len=t-cb->method.s;
75 75
 
76 76
 	/* Cache method id */
77
-	if (parse_method(&cb->method, &cb->method_id) == 0) {
78
-		LOG(L_ERR, "ERROR: parse_cseq: Cannot parse method string\n");
77
+	if (parse_method_name(&cb->method, &cb->method_id)!=0){
78
+		LOG(L_ERR, "Cannot parse method string\n");
79 79
 		goto error;
80 80
 	}
81 81
 
... ...
@@ -43,24 +43,149 @@ static int token_char(char _c)
43 43
  		(_c == '*') || (_c == '_') || (_c == '+') || (_c == '`') ||
44 44
  		(_c == '\'') || (_c == '~') || (_c == '+') || (_c == '`');
45 45
  }
46
- 
47
- 
46
+
47
+
48
+
49
+/** Parse a string containing a method.
50
+ * Parse a method pointed by s & assign its enum bit to method. The string
51
+ * _must_ contain _only_ the method (without trailing or heading whitespace).
52
+ * @return 0 on success, -1 on error
53
+ */
54
+int parse_method_name(str* s, enum request_method* method)
55
+ {
56
+	if (unlikely(!s || !method)) {
57
+		LOG(L_ERR, "Invalid parameter value\n");
58
+		return -1;
59
+	}
60
+	
61
+	if (unlikely(!s->len || (s->s==0))) {
62
+		DBG("No input\n");
63
+		*method = METHOD_OTHER;
64
+		return 0;
65
+	}
66
+	
67
+	switch ((s->s)[0]) {
68
+		/* ordered after probability of aparition on a normal proxy */
69
+		case 'R':
70
+		case 'r':
71
+			if (likely((s->len == 8) &&
72
+					!strncasecmp(s->s + 1, "egister", 7))) {
73
+				*method = METHOD_REGISTER;
74
+				return 0;
75
+			}
76
+			if (likely((s->len==5) && !strncasecmp(s->s + 1, "efer", 4))) {
77
+				*method = METHOD_REFER;
78
+				return 0;
79
+			}
80
+			break;
81
+		case 'A':
82
+		case 'a':
83
+			if (likely((s->len==3) && !strncasecmp(s->s + 1, "ck", 2))) {
84
+				*method = METHOD_ACK;
85
+				return 0;
86
+			}
87
+			break;
88
+		case 'I':
89
+		case 'i':
90
+			if (likely((s->len==6) && !strncasecmp(s->s + 1, "nvite", 5))){
91
+				*method = METHOD_INVITE;
92
+				return 0;
93
+			}
94
+			if (likely((s->len==4) && !strncasecmp(s->s + 1, "nfo", 3))) {
95
+				*method = METHOD_INFO;
96
+				return 0;
97
+			}
98
+			break;
99
+		case 'P':
100
+		case 'p':
101
+			if (likely((s->len==5) && !strncasecmp(s->s + 1, "rack", 4))) {
102
+				*method = METHOD_PRACK;
103
+				return 0;
104
+			}
105
+			if (likely((s->len==7) && !strncasecmp(s->s + 1, "ublish", 6))) {
106
+				*method = METHOD_PUBLISH;
107
+				return 0;
108
+			}
109
+			break;
110
+		case 'C':
111
+		case 'c':
112
+			if (likely((s->len==6) && !strncasecmp(s->s + 1, "ancel", 5))) {
113
+				*method = METHOD_CANCEL;
114
+				return 0;
115
+			}
116
+			break;
117
+		case 'B':
118
+		case 'b':
119
+			if (likely((s->len==3) && !strncasecmp(s->s + 1, "ye", 2))) {
120
+				*method = METHOD_BYE;
121
+				return 0;
122
+			}
123
+			break;
124
+		case 'M':
125
+		case 'm':
126
+			if (likely((s->len==7) && !strncasecmp(s->s + 1, "essage", 6))) {
127
+				*method = METHOD_MESSAGE;
128
+				return 0;
129
+			}
130
+			break;
131
+		case 'O':
132
+		case 'o':
133
+			if (likely((s->len==7) && !strncasecmp(s->s + 1, "ptions", 6))) {
134
+				*method = METHOD_OPTIONS;
135
+				return 0;
136
+			}
137
+			break;
138
+		case 'S':
139
+		case 's':
140
+			if (likely((s->len==9) && !strncasecmp(s->s + 1, "ubscribe", 8))) {
141
+				*method = METHOD_SUBSCRIBE;
142
+				return 0;
143
+			}
144
+			break;
145
+		case 'N':
146
+		case 'n':
147
+			if (likely((s->len==6) && !strncasecmp(s->s + 1, "otify", 5))){
148
+				*method = METHOD_NOTIFY;
149
+				return 0;
150
+			}
151
+			break;
152
+		case 'U':
153
+		case 'u':
154
+			if (likely((s->len==6) && !strncasecmp(s->s + 1, "pdate", 5))){
155
+				*method = METHOD_UPDATE;
156
+				return 0;
157
+			}
158
+			break;
159
+		default:
160
+			break;
161
+	}
162
+/* unknown method */
163
+	*method = METHOD_OTHER;
164
+	return 0;
165
+}
166
+
167
+
168
+
48 169
  /*
49 170
   * Parse a method pointed by _next, assign its enum bit to _method, and update
50 171
   * _next past the method. Returns 1 if parse succeeded and 0 otherwise.
51 172
   */
52
-int parse_method(str* _next, enum request_method* _method) 
173
+static int parse_method_advance(str* _next, enum request_method* _method)
53 174
  {
54
-	 if (!_next || !_method) {
55
-		 LOG(L_ERR, "parse_method: Invalid parameter value\n");
175
+	char* end;
176
+	
177
+	 if (unlikely(!_next || !_method)) {
178
+		 LOG(L_ERR, "Invalid parameter value\n");
56 179
 		 return 0;
57 180
 	 }
58 181
 	 
59
-	 if (!_next->len || !_next->s) {
60
-		 DBG("parse_method: No input\n");
182
+	 if (unlikely(!_next->len || !_next->s)) {
183
+		 DBG("No input\n");
184
+ 		*_method = METHOD_OTHER;
61 185
 		 return 1;
62 186
 	 }
63
-
187
+	end=_next->s+_next->len;
188
+	
64 189
 	 switch ((_next->s)[0]) {
65 190
 	 case 'A':
66 191
 	 case 'a':
... ...
@@ -68,7 +193,7 @@ int parse_method(str* _next, enum request_method* _method)
68 68
  			*_method = METHOD_ACK;
69 69
  			_next->len -= 3;
70 70
  			_next->s += 3;
71
- 			return 1;
71
+			goto found;
72 72
  		} else {
73 73
  			goto unknown;
74 74
  		}
... ...
@@ -79,7 +204,7 @@ int parse_method(str* _next, enum request_method* _method)
79 79
  			*_method = METHOD_BYE;
80 80
  			_next->len -= 3;
81 81
  			_next->s += 3;
82
- 			return 1;
82
+			goto found;
83 83
  		} else {
84 84
  			goto unknown;
85 85
  		}
... ...
@@ -90,7 +215,7 @@ int parse_method(str* _next, enum request_method* _method)
90 90
  			*_method = METHOD_CANCEL;
91 91
  			_next->len -= 6;
92 92
  			_next->s += 6;
93
- 			return 1;
93
+			goto found;
94 94
  		} else {
95 95
  			goto unknown;
96 96
  		}
... ...
@@ -103,14 +228,14 @@ int parse_method(str* _next, enum request_method* _method)
103 103
  				*_method = METHOD_INFO;
104 104
  				_next->len -= 4;
105 105
  				_next->s += 4;
106
- 				return 1;
106
+				goto found;
107 107
  			}
108 108
 
109 109
  			if ((_next->len > 5) && !strncasecmp(_next->s + 2, "vite", 4)) {
110 110
  				*_method = METHOD_INVITE;
111 111
  				_next->len -= 6;
112 112
  				_next->s += 6;
113
- 				return 1;
113
+				goto found;
114 114
  			}
115 115
  		}
116 116
  		goto unknown;
... ...
@@ -121,7 +246,7 @@ int parse_method(str* _next, enum request_method* _method)
121 121
  			*_method = METHOD_MESSAGE;
122 122
  			_next->len -= 7;
123 123
  			_next->s += 7;
124
- 			return 1;
124
+			goto found;
125 125
  		} else {
126 126
  			goto unknown;
127 127
  		}
... ...
@@ -132,7 +257,7 @@ int parse_method(str* _next, enum request_method* _method)
132 132
  			*_method = METHOD_NOTIFY;
133 133
  			_next->len -= 6;
134 134
  			_next->s += 6;
135
- 			return 1;
135
+			goto found;
136 136
  		} else {
137 137
  			goto unknown;
138 138
  		}
... ...
@@ -143,7 +268,7 @@ int parse_method(str* _next, enum request_method* _method)
143 143
  			*_method = METHOD_OPTIONS;
144 144
  			_next->len -= 7;
145 145
  			_next->s += 7;
146
- 			return 1;
146
+			goto found;
147 147
  		} else {
148 148
  			goto unknown;
149 149
  		}
... ...
@@ -154,13 +279,13 @@ int parse_method(str* _next, enum request_method* _method)
154 154
  			*_method = METHOD_PRACK;
155 155
  			_next->len -= 5;
156 156
  			_next->s += 5;
157
- 			return 1;
157
+			goto found;
158 158
  		}
159 159
  		if ((_next->len > 6) && !strncasecmp(_next->s + 1, "ublish", 6)) {
160 160
  			*_method = METHOD_PUBLISH;
161 161
  			_next->len -= 7;
162 162
  			_next->s += 7;
163
- 			return 1;
163
+			goto found;
164 164
  		}
165 165
  		goto unknown;
166 166
 
... ...
@@ -172,14 +297,14 @@ int parse_method(str* _next, enum request_method* _method)
172 172
  				*_method = METHOD_REFER;
173 173
  				_next->len -= 5;
174 174
  				_next->s += 5;
175
- 				return 1;
175
+				goto found;
176 176
  			}
177 177
 
178 178
  			if ((_next->len > 7) && !strncasecmp(_next->s + 2, "gister", 6)) {
179 179
  				*_method = METHOD_REGISTER;
180 180
  				_next->len -= 8;
181 181
  				_next->s += 8;
182
- 				return 1;
182
+				goto found;
183 183
  			}
184 184
  		}
185 185
  		goto unknown;
... ...
@@ -190,7 +315,7 @@ int parse_method(str* _next, enum request_method* _method)
190 190
  			*_method = METHOD_SUBSCRIBE;
191 191
  			_next->len -= 9;
192 192
  			_next->s += 9;
193
- 			return 1;
193
+			goto found;
194 194
  		} else {
195 195
  			goto unknown;
196 196
  		}
... ...
@@ -201,7 +326,7 @@ int parse_method(str* _next, enum request_method* _method)
201 201
  			*_method = METHOD_UPDATE;
202 202
  			_next->len -= 6;
203 203
  			_next->s += 6;
204
- 			return 1;
204
+			goto found;
205 205
  		} else {
206 206
  			goto unknown;
207 207
  		}
... ...
@@ -209,7 +334,7 @@ int parse_method(str* _next, enum request_method* _method)
209 209
  	default:
210 210
  		goto unknown;
211 211
  	}
212
- 
212
+
213 213
  unknown:
214 214
  	if (token_char(*(_next->s))) {
215 215
  		do { 
... ...
@@ -221,6 +346,9 @@ int parse_method(str* _next, enum request_method* _method)
221 221
  	} else {
222 222
  		return 0;
223 223
  	}
224
+found:
225
+	/* check if the method really ends here (if not return 0) */
226
+	return (_next->s>=end) || (!token_char(*(_next->s)));
224 227
  }
225 228
  
226 229
  
... ...
@@ -252,7 +380,7 @@ int parse_method(str* _next, enum request_method* _method)
252 252
  	}
253 253
 
254 254
  	while (1) {
255
- 		if (parse_method(&next, &method)) {
255
+ 		if (parse_method_advance(&next, &method)) {
256 256
  			*_methods |= method;
257 257
  		} else {
258 258
  			LOG(L_ERR, "ERROR: parse_methods: Invalid method\n");
... ...
@@ -39,7 +39,7 @@
39 39
  */
40 40
 int parse_methods(str* _body, unsigned int* _methods);
41 41
 
42
-int parse_method(str* _next, enum request_method* _method);
42
+int parse_method_name(str* s, enum request_method* _method);
43 43
 
44 44
 
45 45
 #endif /* PARSE_METHODS_H */