Mercurial > pidgin
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 |