static const char* is_complete(const char* buf, const char* buf_end, size_t last_len, int* ret) { int ret_cnt = 0; buf = last_len < 3 ? buf : buf + last_len - 3; while (1) { CHECK_EOF(); if (*buf == '\015') { ++buf; CHECK_EOF(); EXPECT_CHAR('\012'); ++ret_cnt; } else if (*buf == '\012') { ++buf; ++ret_cnt; } else { ++buf; ret_cnt = 0; } if (ret_cnt == 2) { return buf; } } *ret = -2; return NULL; }
static int is_complete(const char* buf, const char* buf_end, size_t last_len) { int ret_cnt = 0; buf = last_len < 3 ? buf : buf + last_len - 3; while (1) { CHECK_EOF(); if (*buf == '\r') { ++buf; CHECK_EOF(); EXPECT('\n'); ++ret_cnt; } else if (*buf == '\n') { ++buf; ++ret_cnt; } else { ++buf; ret_cnt = 0; } if (ret_cnt == 2) { return 0; } } return -2; }
static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret) { for (;; ++*num_headers) { CHECK_EOF(); if (*buf == '\015') { ++buf; EXPECT_CHAR('\012'); break; } else if (*buf == '\012') { ++buf; break; } if (*num_headers == max_headers) { *ret = -1; return NULL; } if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) { if (!token_char_map[(unsigned char)*buf]) { *ret = -1; return NULL; } /* parsing name, but do not discard SP before colon, see * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */ headers[*num_headers].name = buf; static const char ALIGNED(16) ranges1[] = "::\x00\037"; int found; buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found); if (!found) { CHECK_EOF(); } while (1) { if (*buf == ':') { break; } else if (*buf < ' ') { *ret = -1; return NULL; } ++buf; CHECK_EOF(); } headers[*num_headers].name_len = buf - headers[*num_headers].name; ++buf; for (;; ++buf) { CHECK_EOF(); if (!(*buf == ' ' || *buf == '\t')) { break; } } } else { headers[*num_headers].name = NULL; headers[*num_headers].name_len = 0; } if ((buf = get_token_to_eol(buf, buf_end, &headers[*num_headers].value, &headers[*num_headers].value_len, ret)) == NULL) { return NULL; } }
static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret) { for (;; ++*num_headers) { CHECK_EOF(); if (*buf == '\015') { ++buf; EXPECT_CHAR('\012'); break; } else if (*buf == '\012') { ++buf; break; } if (*num_headers == max_headers) { *ret = -1; return NULL; } if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) { /* parsing name, but do not discard SP before colon, see * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */ headers[*num_headers].name = buf; static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */ "\"\"" /* 0x22 */ "()" /* 0x28,0x29 */ ",," /* 0x2c */ "//" /* 0x2f */ ":@" /* 0x3a-0x40 */ "[]" /* 0x5b-0x5d */ "{\377"; /* 0x7b-0xff */ int found; buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found); if (!found) { CHECK_EOF(); } while (1) { if (*buf == ':') { break; } else if (!token_char_map[(unsigned char)*buf]) { *ret = -1; return NULL; } ++buf; CHECK_EOF(); } if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) { *ret = -1; return NULL; } ++buf; for (;; ++buf) { CHECK_EOF(); if (!(*buf == ' ' || *buf == '\t')) { break; } } } else {
static const char* parse_headers(const char* buf, const char* buf_end, struct phr_header* headers, size_t* num_headers, size_t max_headers, int* ret) { for (; ; ++*num_headers) { CHECK_EOF(); if (*buf == '\015') { ++buf; EXPECT_CHAR('\012'); break; } else if (*buf == '\012') { ++buf; break; } if (*num_headers == max_headers) { *ret = -1; return NULL; } if (*num_headers == 0 || ! (*buf == ' ' || *buf == '\t')) { /* parsing name, but do not discard SP before colon, see * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */ headers[*num_headers].name = buf; for (; ; ++buf) { CHECK_EOF(); if (*buf == ':') { break; } else if (*buf < ' ') { *ret = -1; return NULL; } } headers[*num_headers].name_len = buf - headers[*num_headers].name; ++buf; for (; ; ++buf) { CHECK_EOF(); if (! (*buf == ' ' || *buf == '\t')) { break; } } } else { headers[*num_headers].name = NULL; headers[*num_headers].name_len = 0; } if ((buf = get_token_to_eol(buf, buf_end, &headers[*num_headers].value, &headers[*num_headers].value_len, ret)) == NULL) { return NULL; } } return buf; }
const char* parse_request(const char* buf, const char* buf_end, const char** method, size_t* method_len, const char** path, size_t* path_len, int* minor_version, struct phr_header* headers, size_t* num_headers, size_t max_headers, int* ret) { /* skip first empty line (some clients add CRLF after POST content) */ CHECK_EOF(); if (*buf == '\015') { ++buf; EXPECT_CHAR('\012'); } else if (*buf == '\012') { ++buf; } /* parse request line */ ADVANCE_TOKEN(*method, *method_len); ++buf; ADVANCE_TOKEN(*path, *path_len); ++buf; if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) { return NULL; } if (*buf == '\015') { ++buf; EXPECT_CHAR('\012'); } else if (*buf == '\012') { ++buf; } else { *ret = -1; return NULL; } return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret); }
static const char* get_token_to_eol(const char* buf, const char* buf_end, const char** token, size_t* token_len, int* ret) { const char* token_start = buf; #ifdef __SSE4_2__ static const char ranges1[] = "\0\010" /* allow HT */ "\012\037" /* allow SP and up to but not including DEL */ "\177\177" /* allow chars w. MSB set */ ; int found; buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found); if (found) goto FOUND_CTL; #else /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */ while (likely(buf_end - buf >= 8)) { #define DOIT() if (unlikely(! IS_PRINTABLE_ASCII(*buf))) goto NonPrintable; ++buf DOIT(); DOIT(); DOIT(); DOIT(); DOIT(); DOIT(); DOIT(); DOIT(); #undef DOIT continue; NonPrintable: if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { goto FOUND_CTL; } ++buf; } #endif for (; ; ++buf) { CHECK_EOF(); if (unlikely(! IS_PRINTABLE_ASCII(*buf))) { if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { goto FOUND_CTL; } } } FOUND_CTL: if (likely(*buf == '\015')) { ++buf; EXPECT_CHAR('\012'); *token_len = buf - 2 - token_start; } else if (*buf == '\012') { *token_len = buf - token_start; ++buf; } else { *ret = -1; return NULL; } *token = token_start; return buf; }
/* *_buf is always within [buf, buf_end) upon success */ static const char *parse_int(const char *buf, const char *buf_end, int *value, int *ret) { int v; CHECK_EOF(); if (!('0' <= *buf && *buf <= '9')) { *ret = -1; return NULL; } v = 0; for (;; ++buf) { CHECK_EOF(); if ('0' <= *buf && *buf <= '9') { v = v * 10 + *buf - '0'; } else { break; } } *value = v; return buf; }
static const char* get_token_to_eol(const char* buf, const char* buf_end, const char** token, size_t* token_len, int* ret) { const char* token_start = buf; while (1) { if (likely(buf_end - buf >= 16)) { unsigned i; for (i = 0; i < 16; i++, ++buf) { if (unlikely((unsigned char)*buf <= '\015') && (*buf == '\015' || *buf == '\012')) { goto EOL_FOUND; } } } else { for (; ; ++buf) { CHECK_EOF(); if (unlikely((unsigned char)*buf <= '\015') && (*buf == '\015' || *buf == '\012')) { goto EOL_FOUND; } } } } EOL_FOUND: if (*buf == '\015') { ++buf; EXPECT_CHAR('\012'); *token_len = buf - 2 - token_start; } else { /* should be: *buf == '\012' */ *token_len = buf - token_start; ++buf; } *token = token_start; return buf; }
static int scc_string_lexer(YYSTYPE *lvalp, YYLTYPE *llocp,scc_lex_t* lex) { unsigned pos; char c; for(pos = 0 ; 1 ; pos++) { c = scc_lex_at(lex,pos); CHECK_EOF(lex,c); if(c == '\\') { // skip escape pos++; continue; } if(c == '"' || c == '%') break; } // finished with a % escape if(c == '%') { scc_lex_push_lexer(lex,scc_string_var_lexer); // some string first ? if(pos > 0) { lvalp->str = scc_lex_gets(lex,pos); //scc_lex_getc(lex); // eat the % scc_unescape_string(lvalp->str); return STRING; } // directly switch to the string var lexer //scc_lex_getc(lex); // eat the % return 0; } lvalp->str = scc_lex_gets(lex,pos); scc_lex_getc(lex); // eat the closing " scc_unescape_string(lvalp->str); // switch back to the previous parser scc_lex_pop_lexer(lex); return STRING; }
void TokenReader::nextToken(Token& t) { int c; if (pushedback) { pushedback = false; t = last; //cout << "popped " << t.toString() << "\n"; return; } skipWhitespace(); t.sval.clear(); t.lineno = lineno; // skipWhitespace always sets pbc CHECK_EOF(c = pbc); pbc = -1; long long ival, divisor; t.type = TT_INVALID; if (c == '"') { CHECK_EOF(NEXTC); // skip quote char while (c != '"') { if (c=='\\') { CHECK_EOF(NEXTC); switch (c) { case 'n': c='\n'; break; case 't': c='\t'; break; case 'b': c='\b'; break; } } t.sval += c; CHECK_EOF(NEXTC); } t.type = TT_STRING; } else if ((c >= '0' && c <= '9') || c == '-') { int radix = 10; bool flt=false; bool minus=false; divisor=1; if (c == '0') { t.sval += c; NEXTC; // won't hurt... if (c == 'x' || c == 'X') { t.sval += c; radix=16; NEXTC; } else if (IS_WHITESPACE_EOF(c)) { t.ival = 0; t.dval = 0; t.type=TT_INTEGER; last = t; //cout << "read " << t.toString() << "\n"; return; } } if (c == '-') { minus=true; t.sval += c; CHECK_EOF(NEXTC); } ival = 0; while (c >= '0' && c <= '9' || c == '.' || c == 'e' || (radix == 16 && ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')))) { minus=false; t.sval += c; if (c == 'e' && (radix != 16)) { flt = true; } if (c == '.') { if (flt) { break; } flt=true; } NEXTC; } pbc=c; if (minus) { t.type = TT_SYMBOL; t.sval = "-"; } else if (flt) { t.type = TT_FLOAT; t.dval = strtod(t.sval.c_str(),NULL); t.ival = (int)t.dval; } else { t.type = TT_INTEGER; t.ival = strtol(t.sval.c_str(),NULL,0); t.dval = t.ival; } } else if (c=='_' || isalpha(c)) { do { t.sval += c; NEXTC; } while (c=='_' || isalnum(c)); t.type = TT_SYMBOL; } else { t.type = TT_SYMBOL; t.sval = c; } //cout << "read " << t.toString() << "\n"; last = t; return; }
int scc_main_lexer(YYSTYPE *lvalp, YYLTYPE *llocp,scc_lex_t* lex) { char c,d; char* str,*ppd; int tpos = 0,pos = 0; int define_line = -1, define_col = -1; scc_keyword_t* keyword; c = scc_lex_at(lex,0); // EOF if(!c) return 0; //scc_lex_get_line_column(lex,&llocp->first_line,&llocp->first_column); // a sym, a keyword or an integer if(SCC_ISALNUM(c) || c == '_') { // read the whole word do { tpos++; c = scc_lex_at(lex,tpos); if(!c) { if(lex->error) return 0; break; } } while(SCC_ISALNUM(c) || c == '_'); // Get the string str = scc_lex_gets(lex,tpos); // Is it an integer ? if(SCC_ISDIGIT(str[0])) { char* end; lvalp->integer = strtol(str,&end,0); if(end[0] != '\0') { scc_lex_error(lex,"Failed to parse integer: '%s'",str); free(str); return 0; } free(str); return INTEGER; } // Is it a define ? if(scc_lex_is_define(lex,str)) { scc_lex_expand_define(lex,str); return -1; } // Is it a keyword ? if((keyword = scc_is_keyword(str,scc_keywords, sizeof(scc_keywords)/sizeof(scc_keyword_t)-1))) { free(str); if(keyword->val >= 0) lvalp->integer = keyword->val; return keyword->type; } // then it's symbol lvalp->str = str; return SYM; } scc_lex_getc(lex); // && &= & || |= | ++ += + -- -= - #define OP_OPEQ_OQDBL(op,eq_val,dbl_type,dbl_val) \ d = scc_lex_at(lex,0); \ CHECK_EOF(lex,d); \ if(d == op) { \ scc_lex_getc(lex); \ lvalp->integer = dbl_val; \ return dbl_type; \ } else if(d == '=') { \ scc_lex_getc(lex); \ lvalp->integer = eq_val; \ return ASSIGN; \ } \ lvalp->integer = op; \ return op // == = != ! >= > <= < *= * #define OP_OPEQ(op,eq_type,eq_val) \ d = scc_lex_at(lex,0); \ CHECK_EOF(lex,d); \ if(d == '=') { \ scc_lex_getc(lex); \ lvalp->integer = eq_val; \ return eq_type; \ } \ lvalp->integer = op; \ return op \ switch(c) { // && &= & case '&': OP_OPEQ_OQDBL('&',AAND,LAND,LAND); // || |= | case '|': OP_OPEQ_OQDBL('|',AOR,LOR,LOR); // ++ += + case '+': OP_OPEQ_OQDBL('+',AADD,SUFFIX,INC); // -- -= - case '-': OP_OPEQ_OQDBL('-',ASUB,SUFFIX,DEC); break; case '=': d = scc_lex_at(lex,0); CHECK_EOF(lex,d); if(d == '=') { scc_lex_getc(lex); lvalp->integer = EQ; return EQ; } lvalp->integer = '='; return ASSIGN; // != ! case '!': OP_OPEQ('!',NEQ,NEQ); // >= > case '>': OP_OPEQ('>',GE,GE); // <= < case '<': OP_OPEQ('<',LE,LE); // *= * case '*': OP_OPEQ('*',ASSIGN,AADD); // /= // /* // / case '/': d = scc_lex_at(lex,0); if(d == '=') { // divide and assign scc_lex_getc(lex); lvalp->integer = ADIV; return ASSIGN; } else if(d == '/') { // single line comments tpos = scc_lex_strchr(lex,1,'\n'); if(tpos > 0) scc_lex_drop(lex,tpos+1); return -1; } else if(d == '*') { // multi line comments do { tpos = scc_lex_strchr(lex,tpos+1,'/'); if(tpos < 0) { // TODO warn instead if(!lex->error) scc_lex_error(lex,"Unfinished multi line comment"); return 0; } } while(scc_lex_at(lex,tpos-1) != '*'); scc_lex_drop(lex,tpos+1); return -1; } // divide lvalp->integer = '/'; return '/'; // :: : case ':': d = scc_lex_at(lex,0); if(d == ':') { scc_lex_getc(lex); return NS; } lvalp->integer = ':'; return ':'; // ; , @ ( ) [ ] { } ? case ';': case ',': case '@': case '(': case ')': case '[': case ']': case '{': case '}': case '?': lvalp->integer = c; return c; // single chars case '\'': c = scc_lex_getc(lex); if(c == '\\') c = scc_lex_getc(lex); CHECK_EOF(lex,c); d = scc_lex_getc(lex); CHECK_EOF(lex,d); if(d != '\'') { scc_lex_error(lex,"Unterminated character constant."); return 0; } lvalp->integer = c; return INTEGER; // strings case '"': scc_lex_push_lexer(lex,scc_string_lexer); return 0; // pre precessor case '#': // read the directive name c = scc_lex_at(lex,tpos); CHECK_EOF(lex,c); // skip initial spaces while(c == ' ' || c == '\t') { tpos++; c = scc_lex_at(lex,tpos); CHECK_EOF(lex,c); } // check that the first char is an alpha if(!SCC_ISALPHA(c)) { scc_lex_error(lex,"Invalid preprocessor directive."); return 0; } // drop the spaces scc_lex_drop(lex,tpos); // read the name tpos = 0; do { tpos++; c = scc_lex_at(lex,tpos); CHECK_EOF(lex,c); } while(SCC_ISALPHA(c)); // check we ended on a space if(c != ' ' && c != '\t' && c != '\n') { scc_lex_error(lex,"Invalid preprocessor directive."); return 0; } // read the directive ppd = scc_lex_gets(lex,tpos); str = NULL; while(1) { // skip spaces tpos = 0; while(c == ' ' || c == '\t') { tpos++; c = scc_lex_at(lex,tpos); CHECK_EOF(lex,c); } // only space, that's it for now if(c == '\n') { scc_lex_drop(lex,tpos+1); break; } else scc_lex_drop(lex,tpos); // Store the arg start position if(define_line < 0) scc_lex_get_line_column(lex,&define_line,&define_col); // find the eol tpos = scc_lex_strchr(lex,0,'\n'); if(tpos < 0) { // we should do better here scc_lex_error(lex,"Unexpected eof"); return 0; } // count the leading spaces pos = tpos; do { pos--; c = scc_lex_at(lex,pos); CHECK_EOF(lex,c); } while(c == ' ' || c == '\t'); // not finished on a \, we are done if(c != '\\') { str = scc_lex_strcat(lex,str,pos+1); break; } // read that line str = scc_lex_strcat(lex,str,pos); // and drop the \ and the spaces scc_lex_drop(lex,tpos+1-pos); } // call the preproc tpos = scc_preproc_lexer(lex,ppd,str,define_line,define_col); free(ppd); if(str) free(str); return tpos; case ' ': case '\n': case '\t': do { c = scc_lex_at(lex,tpos); tpos++; } while (c == ' ' || c == '\n' || c == '\t'); scc_lex_drop(lex,tpos-1); return -1; default: scc_lex_error(lex,"Unrecognized character: '%c'",c); return 0; } }
int phr_parse_request(const char* _buf, size_t len, const char** method, size_t* method_len, const char** path, size_t* path_len, int* minor_version, struct phr_header* headers, size_t* num_headers, size_t last_len) { const char * buf = _buf, * buf_end = buf + len; size_t max_headers; /* if last_len != 0, check if the request is complete (a fast countermeasure againt slowloris */ if (last_len != 0) { int r = is_complete(buf, buf_end, last_len); if (r != 0) { return r; } } /* skip first empty line (some clients add CRLF after POST content) */ CHECK_EOF(); if (*buf == '\r') { ++buf; EXPECT('\n'); } else if (*buf == '\n') { ++buf; } /* parse request line */ *method = buf; ADVANCE_TOKEN(); *method_len = buf - *method; ++buf; *path = buf; ADVANCE_TOKEN(); *path_len = buf - *path; ++buf; EXPECT('H'); EXPECT('T'); EXPECT('T'); EXPECT('P'); EXPECT('/'); EXPECT('1'); EXPECT('.'); *minor_version = 0; for (; ; ++buf) { CHECK_EOF(); if ('0' <= *buf && *buf <= '9') { *minor_version = *minor_version * 10 + *buf - '0'; } else { break; } } if (*buf == '\r') { ++buf; EXPECT('\n'); } else if (*buf == '\n') { ++buf; } else { return -1; } /* parse headers */ max_headers = *num_headers; for (*num_headers = 0; ; ++*num_headers) { CHECK_EOF(); if (*buf == '\r') { ++buf; EXPECT('\n'); break; } else if (*buf == '\n') { ++buf; break; } if (*num_headers == max_headers) { return -1; } if (*num_headers == 0 || ! (*buf == ' ' || *buf == '\t')) { /* parsing name */ headers[*num_headers].name = buf; for (; ; ++buf) { CHECK_EOF(); if (*buf == ':') { break; } else if (*buf < ' ') { return -1; } } headers[*num_headers].name_len = buf - headers[*num_headers].name; ++buf; for (; ; ++buf) { CHECK_EOF(); if (! (*buf == ' ' || *buf == '\t')) { break; } } } else { headers[*num_headers].name = NULL; headers[*num_headers].name_len = 0; } headers[*num_headers].value = buf; for (; ; ++buf) { CHECK_EOF(); if (*buf == '\r') { headers[*num_headers].value_len = buf - headers[*num_headers].value; ++buf; EXPECT('\n'); break; } else if (*buf == '\n') { headers[*num_headers].value_len = buf - headers[*num_headers].value; ++buf; break; } } } return buf - _buf; }
static int scc_string_var_lexer(YYSTYPE *lvalp, YYLTYPE *llocp,scc_lex_t* lex) { char c,d; char* esc = "%ivVnsfc"; int tpos = 0; scc_str_t* str; scc_lex_pop_lexer(lex); c = scc_lex_getc(lex); // eat the % CHECK_EOF(lex,c); c = scc_lex_at(lex,0); // get the command CHECK_EOF(lex,c); // check that it's a known escape if(!strchr(esc,c)) return 0; else scc_lex_getc(lex); if(c == '%') { lvalp->str = strdup("%"); d = scc_lex_at(lex,0); // little hack to get rid of the usless empty string if(d == '"') { scc_lex_getc(lex); scc_lex_pop_lexer(lex); } return STRING; } d = scc_lex_at(lex,0); CHECK_EOF(lex,d); if(d != '{') return 0; // read the word do { tpos++; d = scc_lex_at(lex,tpos); if(!d) { if(lex->error) return 0; break; } } while(SCC_ISALNUM(d) || d == '_'); if(d != '}') return 0; lvalp->strvar = str = calloc(1,sizeof(scc_str_t)); // read out the string scc_lex_getc(lex); // { str->str = scc_lex_gets(lex,tpos-1); scc_lex_getc(lex); // } switch(c) { case 'i': str->type = SCC_STR_INT; break; case 'v': str->type = SCC_STR_VERB; break; case 'V': str->type = SCC_STR_VOICE; break; case 'n': str->type = SCC_STR_NAME; break; case 's': str->type = SCC_STR_STR; break; case 'f': str->type = SCC_STR_FONT; break; case 'c': { char* end; int val = strtol(str->str,&end,0); if(end[0] != '\0' || val < 0 || val > 255) { scc_lex_error(lex,"Invalid color number: %s\n",str->str); return 0; } str->type = SCC_STR_COLOR; str->str = realloc(str->str,2); SCC_SET_16LE(str->str,0,val); } break; } d = scc_lex_at(lex,0); if(d == '"') { scc_lex_getc(lex); scc_lex_pop_lexer(lex); } return STRVAR; }
static size_t *process_range(h2o_mem_pool_t *pool, h2o_iovec_t *range_value, size_t file_size, size_t *ret) { #define CHECK_EOF() \ if (buf == buf_end) \ return NULL; #define CHECK_OVERFLOW(range) \ if (range == SIZE_MAX) \ return NULL; size_t range_start = SIZE_MAX, range_count = 0; char *buf = range_value->base, *buf_end = buf + range_value->len; int needs_comma = 0; H2O_VECTOR(size_t) ranges = {}; if (range_value->len < 6 || memcmp(buf, "bytes=", 6) != 0) return NULL; buf += 6; CHECK_EOF(); /* most range requests contain only one range */ do { while (1) { if (*buf != ',') { if (needs_comma) return NULL; break; } needs_comma = 0; buf++; while (H2O_UNLIKELY(*buf == ' ') || H2O_UNLIKELY(*buf == '\t')) { buf++; CHECK_EOF(); } } if (H2O_UNLIKELY(buf == buf_end)) break; if (H2O_LIKELY((range_start = h2o_strtosizefwd(&buf, buf_end - buf)) != SIZE_MAX)) { CHECK_EOF(); if (*buf++ != '-') return NULL; range_count = h2o_strtosizefwd(&buf, buf_end - buf); if (H2O_UNLIKELY(range_start >= file_size)) { range_start = SIZE_MAX; } else if (H2O_LIKELY(range_count != SIZE_MAX)) { if (H2O_UNLIKELY(range_count > file_size - 1)) range_count = file_size - 1; if (H2O_LIKELY(range_start <= range_count)) range_count -= range_start - 1; else range_start = SIZE_MAX; } else { range_count = file_size - range_start; } } else if (H2O_LIKELY(*buf++ == '-')) { CHECK_EOF(); range_count = h2o_strtosizefwd(&buf, buf_end - buf); if (H2O_UNLIKELY(range_count == SIZE_MAX)) return NULL; if (H2O_LIKELY(range_count != 0)) { if (H2O_UNLIKELY(range_count > file_size)) range_count = file_size; range_start = file_size - range_count; } else { range_start = SIZE_MAX; } } else { return NULL; } if (H2O_LIKELY(range_start != SIZE_MAX)) { h2o_vector_reserve(pool, &ranges, ranges.size + 2); ranges.entries[ranges.size++] = range_start; ranges.entries[ranges.size++] = range_count; } if (buf != buf_end) while (H2O_UNLIKELY(*buf == ' ') || H2O_UNLIKELY(*buf == '\t')) { buf++; CHECK_EOF(); } needs_comma = 1; } while (H2O_UNLIKELY(buf < buf_end)); *ret = ranges.size / 2; return ranges.entries; #undef CHECK_EOF #undef CHECK_OVERFLOW }
static ssize_t parse_proxy_line(char *src, size_t len, struct sockaddr *sa, socklen_t *salen) { #define CHECK_EOF() \ if (p == end) \ return -2 #define EXPECT_CHAR(ch) \ do { \ CHECK_EOF(); \ if (*p++ != ch) \ return -1; \ } while (0) #define SKIP_TO_WS() \ do { \ do { \ CHECK_EOF(); \ } while (*p++ != ' '); \ --p; \ } while (0) char *p = src, *end = p + len; void *addr; in_port_t *port; /* "PROXY "*/ EXPECT_CHAR('P'); EXPECT_CHAR('R'); EXPECT_CHAR('O'); EXPECT_CHAR('X'); EXPECT_CHAR('Y'); EXPECT_CHAR(' '); /* "TCP[46] " */ CHECK_EOF(); if (*p++ != 'T') { *salen = 0; /* indicate that no data has been obtained */ goto SkipToEOL; } EXPECT_CHAR('C'); EXPECT_CHAR('P'); CHECK_EOF(); switch (*p++) { case '4': *salen = sizeof(struct sockaddr_in); *((struct sockaddr_in *)sa) = (struct sockaddr_in){}; sa->sa_family = AF_INET; addr = &((struct sockaddr_in *)sa)->sin_addr; port = &((struct sockaddr_in *)sa)->sin_port; break; case '6': *salen = sizeof(struct sockaddr_in6); *((struct sockaddr_in6 *)sa) = (struct sockaddr_in6){}; sa->sa_family = AF_INET6; addr = &((struct sockaddr_in6 *)sa)->sin6_addr; port = &((struct sockaddr_in6 *)sa)->sin6_port; break; default: return -1; } EXPECT_CHAR(' '); /* parse peer address */ char *addr_start = p; SKIP_TO_WS(); *p = '\0'; if (inet_pton(sa->sa_family, addr_start, addr) != 1) return -1; *p++ = ' '; /* skip local address */ SKIP_TO_WS(); ++p; /* parse peer port */ char *port_start = p; SKIP_TO_WS(); *p = '\0'; unsigned short usval; if (sscanf(port_start, "%hu", &usval) != 1) return -1; *port = htons(usval); *p++ = ' '; SkipToEOL: do { CHECK_EOF(); } while (*p++ != '\r'); CHECK_EOF(); if (*p++ != '\n') return -2; return p - src; #undef CHECK_EOF #undef EXPECT_CHAR #undef SKIP_TO_WS }
int airport::Uriparser::nu_parse_uri(const char* _buf, size_t len, const char** scheme, size_t *scheme_len, const char **host, size_t *host_len, int *port, const char **path_query, int*path_query_len, const char **fragment, int*fragment_len) { const char * buf = _buf, * buf_end = buf + len; *scheme = buf; for (;;++buf) { CHECK_EOF(); if (':' == *buf) { break; } } *scheme_len = buf - *scheme; EXPECT(':'); EXPECT('/'); EXPECT('/'); *host = buf; *port = 0; *host_len = 0; *path_query_len = 0; *fragment_len = 0; for (;;++buf) { if (buf == buf_end) { *host_len = buf - *host; return 0; } if (':' == *buf) { /* with port */ *host_len = buf - *host; buf++; *port = 0; for (;'0' <= *buf && *buf <= '9';buf++) { if (buf == buf_end) { return 0; } *port = *port * 10 + (*buf - '0'); } if (buf == buf_end) { return 0; } break; } if ('/' == *buf) { /* no port */ *host_len = buf - *host; break; } } if (*host_len==0) { buf = _buf; } *path_query = buf; *path_query_len = buf_end - buf; for (;;++buf) { if (buf == buf_end) { return 0; } if ('#' == *buf) { *path_query_len = buf - *path_query; buf ++; if (buf == buf_end) { return 0; } *fragment = buf; *fragment_len = buf_end - buf; break; } } return 0; }