comparison src/util.c @ 13520:c836ba676c7c

[gaim-migrate @ 15896] Fix a potential crash when we're returning the page headers as well as the body. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Thu, 16 Mar 2006 20:25:01 +0000
parents 231c58da452d
children 097ae11c67e0
comparison
equal deleted inserted replaced
13519:d6dd68a8be06 13520:c836ba676c7c
3158 3158
3159 /* This is still technically wrong, since headers are case-insensitive 3159 /* This is still technically wrong, since headers are case-insensitive
3160 * [RFC 2616, section 4.2], though this ought to catch the normal case. 3160 * [RFC 2616, section 4.2], though this ought to catch the normal case.
3161 * Note: data is _not_ nul-terminated. 3161 * Note: data is _not_ nul-terminated.
3162 */ 3162 */
3163 if (data_len > 16) { 3163 if(data_len > 16) {
3164 p = strncmp(data, "Content-Length: ", 16) == 0 ? data : NULL; 3164 p = (strncmp(data, "Content-Length: ", 16) == 0) ? data : NULL;
3165 if (!p) { 3165 if(!p)
3166 p = g_strstr_len(data, data_len, "\nContent-Length: ");
3167 if (p)
3168 p += 1;
3169 }
3170 if (!p)
3171 p = (strncmp(data, "CONTENT-LENGTH: ", 16) == 0) 3166 p = (strncmp(data, "CONTENT-LENGTH: ", 16) == 0)
3172 ? data : NULL; 3167 ? data : NULL;
3173 if (!p) { 3168 if(!p) {
3174 p = g_strstr_len(data, data_len, "\nContent-Length: "); 3169 p = g_strstr_len(data, data_len, "\nContent-Length: ");
3175 if (p) 3170 if (p)
3176 p++; 3171 p++;
3177 } 3172 }
3178 if (!p) { 3173 if(!p) {
3179 p = g_strstr_len(data, data_len, "\nCONTENT-LENGTH: "); 3174 p = g_strstr_len(data, data_len, "\nCONTENT-LENGTH: ");
3180 if (p) 3175 if (p)
3181 p++; 3176 p++;
3182 } 3177 }
3183 3178
3184 if (p) 3179 if(p)
3185 p += 16; 3180 p += 16;
3186 } 3181 }
3187 3182
3188 /* If we can find a Content-Length header at all, try to sscanf it. 3183 /* If we can find a Content-Length header at all, try to sscanf it.
3189 * Response headers should end with at least \r\n, so sscanf is safe, 3184 * Response headers should end with at least \r\n, so sscanf is safe,
3229 3224
3230 /** See if we've reached the end of the headers yet */ 3225 /** See if we've reached the end of the headers yet */
3231 if((tmp = strstr(gfud->webdata, "\r\n\r\n"))) { 3226 if((tmp = strstr(gfud->webdata, "\r\n\r\n"))) {
3232 char * new_data; 3227 char * new_data;
3233 guint header_len = (tmp + 4 - gfud->webdata); 3228 guint header_len = (tmp + 4 - gfud->webdata);
3234 size_t content_len, body_len = 0; 3229 size_t content_len;
3235 3230
3236 gaim_debug_misc("gaim_url_fetch", "Response headers: '%.*s'\n", 3231 gaim_debug_misc("gaim_url_fetch", "Response headers: '%.*s'\n",
3237 header_len, gfud->webdata); 3232 header_len, gfud->webdata);
3238 3233
3239 /* See if we can find a redirect. */ 3234 /* See if we can find a redirect. */
3240 if (parse_redirect(gfud->webdata, header_len, sock, gfud)) 3235 if(parse_redirect(gfud->webdata, header_len, sock, gfud))
3241 return; 3236 return;
3242 3237
3243 gfud->got_headers = TRUE; 3238 gfud->got_headers = TRUE;
3244 3239
3245 /* No redirect. See if we can find a content length. */ 3240 /* No redirect. See if we can find a content length. */
3246 content_len = parse_content_len(gfud->webdata, header_len); 3241 content_len = parse_content_len(gfud->webdata, header_len);
3247 3242
3248 if (content_len == 0) 3243 if(content_len == 0) {
3249 {
3250 /* We'll stick with an initial 8192 */ 3244 /* We'll stick with an initial 8192 */
3251 content_len = 8192; 3245 content_len = 8192;
3252 } 3246 } else {
3253 else
3254 {
3255 gfud->has_explicit_data_len = TRUE; 3247 gfud->has_explicit_data_len = TRUE;
3256 } 3248 }
3257 3249
3258 content_len = MAX(content_len, body_len);
3259 3250
3260 /* If we're returning the headers too, we don't need to clean them out */ 3251 /* If we're returning the headers too, we don't need to clean them out */
3261 if (gfud->include_headers) { 3252 if(gfud->include_headers) {
3262 gfud->data_len = content_len + header_len; 3253 gfud->data_len = content_len + header_len;
3254 gfud->webdata = g_realloc(gfud->webdata, gfud->data_len);
3263 } else { 3255 } else {
3264 3256 size_t body_len = 0;
3265 if (gfud->len > (header_len + 1)) 3257
3258 if(gfud->len > (header_len + 1))
3266 body_len = (gfud->len - header_len); 3259 body_len = (gfud->len - header_len);
3267 3260
3261 content_len = MAX(content_len, body_len);
3268 3262
3269 new_data = g_try_malloc(content_len); 3263 new_data = g_try_malloc(content_len);
3270 if (new_data == NULL) { 3264 if(new_data == NULL) {
3271 gaim_debug_error("gaim_url_fetch", "Failed to allocate %u bytes: %s\n", 3265 gaim_debug_error("gaim_url_fetch", "Failed to allocate %u bytes: %s\n",
3272 content_len, strerror(errno)); 3266 content_len, strerror(errno));
3273 gaim_input_remove(gfud->inpa); 3267 gaim_input_remove(gfud->inpa);
3274 close(sock); 3268 close(sock);
3275 gfud->callback(gfud->user_data, NULL, 0); 3269 gfud->callback(gfud->user_data, NULL, 0);
3277 3271
3278 return; 3272 return;
3279 } 3273 }
3280 3274
3281 /* We may have read part of the body when reading the headers, don't lose it */ 3275 /* We may have read part of the body when reading the headers, don't lose it */
3282 if (body_len > 0) { 3276 if(body_len > 0) {
3283 tmp += 4; 3277 tmp += 4;
3284 memcpy(new_data, tmp, body_len); 3278 memcpy(new_data, tmp, body_len);
3285 } 3279 }
3286 3280
3287 /* Out with the old... */ 3281 /* Out with the old... */
3288 g_free(gfud->webdata); 3282 g_free(gfud->webdata);
3289 gfud->webdata = NULL;
3290 3283
3291 /* In with the new. */ 3284 /* In with the new. */
3292 gfud->len = body_len; 3285 gfud->len = body_len;
3293 gfud->data_len = content_len; 3286 gfud->data_len = content_len;
3294 gfud->webdata = new_data; 3287 gfud->webdata = new_data;
3295 } 3288 }
3296 } 3289 }
3297 } 3290 }
3298 3291
3299 if (gfud->has_explicit_data_len && gfud->len >= gfud->data_len) 3292 if(gfud->has_explicit_data_len && gfud->len >= gfud->data_len) {
3300 {
3301 got_eof = TRUE; 3293 got_eof = TRUE;
3302 break; 3294 break;
3303 } 3295 }
3304 } 3296 }
3305 3297
3306 if(len <= 0) { 3298 if(len <= 0) {
3307 if(errno == EAGAIN) { 3299 if(errno == EAGAIN) {
3308 return; 3300 return;
3309 } else if (errno != ETIMEDOUT) { 3301 } else if(errno != ETIMEDOUT) {
3310 got_eof = TRUE; 3302 got_eof = TRUE;
3311 } else { 3303 } else {
3312 gaim_input_remove(gfud->inpa); 3304 gaim_input_remove(gfud->inpa);
3313 close(sock); 3305 close(sock);
3314 3306
3317 destroy_fetch_url_data(gfud); 3309 destroy_fetch_url_data(gfud);
3318 return; 3310 return;
3319 } 3311 }
3320 } 3312 }
3321 3313
3322 if (got_eof) { 3314 if(got_eof) {
3323 gfud->webdata = g_realloc(gfud->webdata, gfud->len + 1); 3315 gfud->webdata = g_realloc(gfud->webdata, gfud->len + 1);
3324 gfud->webdata[gfud->len] = '\0'; 3316 gfud->webdata[gfud->len] = '\0';
3325 3317
3326 /* gaim_debug_misc("gaim_url_fetch", "Received: '%s'\n", gfud->webdata); */ 3318 /* gaim_debug_misc("gaim_url_fetch", "Received: '%s'\n", gfud->webdata); */
3327 3319