这里的重点照样当状况为解析 URI 的时刻碰到了空格的处理,膳绫擎也解释过了,一旦碰到这种情况,则会认为 URI 已经解析好了,并且将状况修改为 s_req_http_start。也就是说,有“Bug”的那个数据包
好的,接下来我们看看 s_req_http_start 怎么处理:
如代码所见,若当缁ご态为 s_req_http_start,则先断定当缁ぶ符是不是合标。因为就 HTTP 请求包体的格局来看,如不雅 URI 解析停止的话,理应出现类似 HTTP/1.1 的┞封么一个版本申明。所以这个时刻 http-parser 会直接断定当缁ぶ符是否为 H。
- 若是 H,则将状况改为 s_req_http_H 并持续扫描轮回的下一位,同理在 s_req_http_H 下若合法状况就会变成 s_req_http_HT,以词攀类推;
+若是空格,则认为是多余的空格,那么当缁ご态不做任何改变,并持续下一?扫描;
- 但如不雅当缁ぶ符既不是空格也不是 H,那么好了,http-parser 直接认为你的请求包不合法,将你本次的解析设置缺点 HPE_INVALID_CONSTANT 并 goto 到 error 代码块。
Nginx
至此,我们根本上已经明白了原因了:
http-parser 认为在 HTTP 请求包体中,第一行的 URI 解析阶段一旦出现了空格,就会认为 URI 解析完成,继而解析 HTTP 协定版本。但若此时紧跟着的不是 HTTP 协定版本的标准格局,http-parser 就会认为你这是一个 HPE_INVALID_CONSTANT 的数据包。
不过,我们照样持续看看它的 error 代码块吧:
- error:
- if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
- SET_ERRNO(HPE_UNKNOWN);
- }
- RETURN(p - data);
这段代码中起首断定一下当跳到这段代码的时刻有没有设置缺点,若没有设置缺点则将缺点设置为未知缺点(HPE_UNKNOWN),然后返回已解析的数据包长度。
p 是当前解析字符指针,data 是这个数据包的肇端指针,所以 p - data 就是已解析的数据长度。如不雅成功解析完,这个数据包理论上是等于这个数据包的完全长度,若不等则理论上解释白定是半途掉足提前返回。
回到 node_http_parser.cc
看完了 http-parser 的道理后,很多处所茅塞顿开。如今我们回到它的调用地 node_http_parser.cc 持续浏览吧。
- Local<Value> Execute(char* data, size_t len) {
- ...
- size_t nparsed =
- http_parser_execute(&parser_, &settings, data, len);
- Local<Integer> nparsed_obj = Integer::New(env()->isolate(), nparsed);
- if (!parser_.upgrade && nparsed != len) {
- enum http_errno err = HTTP_PARSER_ERRNO(&parser_);
- Local<Value> e = Exception::Error(env()->parse_error_string());
- Local<Object> obj = e->ToObject(env()->isolate());
- obj->Set(env()->bytes_parsed_string(), nparsed_obj);
- obj->
推荐阅读
黑客在渗入渗出一个网站时,受制于本身的黑客才能以及小我思维宽度,在想尽了一切办法后,却一无所得,最终就不得不走上了暴力破解这一条陆辜暴力破解的道理就是穷举法,其根本思惟是根据标题标部分前提>>>详细阅读
本文标题:Node.js中遇到含空格URL的神奇“Bug”——小范围深入HTTP协议
地址:http://www.17bianji.com/lsqh/39781.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示