Skip to content

Commit c8cd771

Browse files
committed
Make header parsing more robust
1 parent 252c38c commit c8cd771

1 file changed

Lines changed: 43 additions & 46 deletions

File tree

CGDWebServer/Core/GCDWebServerConnection.m

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -579,69 +579,66 @@ - (void)_readRequestHeaders {
579579

580580
if (extraData) {
581581
NSString* requestMethod = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestMethod(_requestMessage)); // Method verbs are case-sensitive and uppercase
582-
DCHECK(requestMethod);
583582
if ([[_server class] shouldAutomaticallyMapHEADToGET] && [requestMethod isEqualToString:@"HEAD"]) {
584583
requestMethod = @"GET";
585584
_virtualHEAD = YES;
586585
}
587586
NSURL* requestURL = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestURL(_requestMessage));
588-
DCHECK(requestURL);
589-
NSString* requestPath = GCDWebServerUnescapeURLString(ARC_BRIDGE_RELEASE(CFURLCopyPath((CFURLRef)requestURL))); // Don't use -[NSURL path] which strips the ending slash
590-
DCHECK(requestPath);
591-
NSDictionary* requestQuery = nil;
592-
NSString* queryString = ARC_BRIDGE_RELEASE(CFURLCopyQueryString((CFURLRef)requestURL, NULL)); // Don't use -[NSURL query] to make sure query is not unescaped;
593-
if (queryString.length) {
594-
requestQuery = GCDWebServerParseURLEncodedForm(queryString);
595-
DCHECK(requestQuery);
596-
}
587+
NSString* requestPath = requestURL ? GCDWebServerUnescapeURLString(ARC_BRIDGE_RELEASE(CFURLCopyPath((CFURLRef)requestURL))) : nil; // Don't use -[NSURL path] which strips the ending slash
588+
NSString* queryString = requestURL ? ARC_BRIDGE_RELEASE(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped;
589+
NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{};
597590
NSDictionary* requestHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones
598-
DCHECK(requestHeaders);
599-
for (_handler in _server.handlers) {
600-
_request = ARC_RETAIN(_handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery));
601-
if (_request) {
602-
break;
591+
if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) {
592+
for (_handler in _server.handlers) {
593+
_request = ARC_RETAIN(_handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery));
594+
if (_request) {
595+
break;
596+
}
603597
}
604-
}
605-
if (_request) {
606-
if ([_request hasBody]) {
607-
[_request prepareForWriting];
608-
if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) {
609-
NSString* expectHeader = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyHeaderFieldValue(_requestMessage, CFSTR("Expect")));
610-
if (expectHeader) {
611-
if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) {
612-
[self _writeData:_continueData withCompletionBlock:^(BOOL success) {
613-
614-
if (success) {
615-
if (_request.usesChunkedTransferEncoding) {
616-
[self _readChunkedBodyWithInitialData:extraData];
617-
} else {
618-
[self _readBodyWithLength:_request.contentLength initialData:extraData];
598+
if (_request) {
599+
if ([_request hasBody]) {
600+
[_request prepareForWriting];
601+
if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) {
602+
NSString* expectHeader = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyHeaderFieldValue(_requestMessage, CFSTR("Expect")));
603+
if (expectHeader) {
604+
if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) {
605+
[self _writeData:_continueData withCompletionBlock:^(BOOL success) {
606+
607+
if (success) {
608+
if (_request.usesChunkedTransferEncoding) {
609+
[self _readChunkedBodyWithInitialData:extraData];
610+
} else {
611+
[self _readBodyWithLength:_request.contentLength initialData:extraData];
612+
}
619613
}
620-
}
621-
622-
}];
614+
615+
}];
616+
} else {
617+
LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket);
618+
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed];
619+
}
623620
} else {
624-
LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket);
625-
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed];
621+
if (_request.usesChunkedTransferEncoding) {
622+
[self _readChunkedBodyWithInitialData:extraData];
623+
} else {
624+
[self _readBodyWithLength:_request.contentLength initialData:extraData];
625+
}
626626
}
627627
} else {
628-
if (_request.usesChunkedTransferEncoding) {
629-
[self _readChunkedBodyWithInitialData:extraData];
630-
} else {
631-
[self _readBodyWithLength:_request.contentLength initialData:extraData];
632-
}
628+
LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket);
629+
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest];
633630
}
634631
} else {
635-
LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket);
636-
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest];
632+
[self _processRequest];
637633
}
638634
} else {
639-
[self _processRequest];
635+
_request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery];
636+
DCHECK(_request);
637+
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed];
640638
}
641639
} else {
642-
_request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery];
643-
DCHECK(_request);
644-
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed];
640+
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
641+
DNOT_REACHED();
645642
}
646643
} else {
647644
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];

0 commit comments

Comments
 (0)