diff --git a/src/HttpServer.cc b/src/HttpServer.cc index e3735140..3e662e93 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -1585,8 +1585,9 @@ int start_listen(event_base *evbase, Sessions *sessions, const Config *config) { addrinfo hints; int r; - char service[10]; - snprintf(service, sizeof(service), "%u", config->port); + + auto service = util::utos(config->port); + memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; @@ -1600,7 +1601,7 @@ int start_listen(event_base *evbase, Sessions *sessions, const Config *config) auto listen_handler = listen_handler_store.get(); addrinfo *res, *rp; - r = getaddrinfo(nullptr, service, &hints, &res); + r = getaddrinfo(nullptr, service.c_str(), &hints, &res); if(r != 0) { std::cerr << "getaddrinfo() failed: " << gai_strerror(r) << std::endl; return -1; diff --git a/src/shrpx-unittest.cc b/src/shrpx-unittest.cc index e6e14968..0a6c16fc 100644 --- a/src/shrpx-unittest.cc +++ b/src/shrpx-unittest.cc @@ -118,6 +118,7 @@ int main(int argc, char* argv[]) shrpx::test_util_to_base64) || !CU_add_test(pSuite, "util_percent_encode_token", shrpx::test_util_percent_encode_token) || + !CU_add_test(pSuite, "util_utox", shrpx::test_util_utox) || !CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)) { CU_cleanup_registry(); return CU_get_error(); diff --git a/src/shrpx.cc b/src/shrpx.cc index c283d288..b9a910f0 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -83,9 +83,8 @@ int resolve_hostname(sockaddr_union *addr, size_t *addrlen, { addrinfo hints; int rv; - char service[10]; - snprintf(service, sizeof(service), "%u", port); + auto service = util::utos(port); memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = family; @@ -95,7 +94,7 @@ int resolve_hostname(sockaddr_union *addr, size_t *addrlen, #endif // AI_ADDRCONFIG addrinfo *res; - rv = getaddrinfo(hostname, service, &hints, &res); + rv = getaddrinfo(hostname, service.c_str(), &hints, &res); if(rv != 0) { LOG(FATAL) << "Unable to resolve address for " << hostname << ": " << gai_strerror(rv); @@ -136,8 +135,8 @@ evconnlistener* create_evlistener(ListenHandler *handler, int family) addrinfo hints; int fd = -1; int r; - char service[10]; - snprintf(service, sizeof(service), "%u", get_config()->port); + + auto service = util::utos(get_config()->port); memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; @@ -147,7 +146,7 @@ evconnlistener* create_evlistener(ListenHandler *handler, int family) #endif // AI_ADDRCONFIG addrinfo *res, *rp; - r = getaddrinfo(get_config()->host, service, &hints, &res); + r = getaddrinfo(get_config()->host, service.c_str(), &hints, &res); if(r != 0) { if(LOG_ENABLED(INFO)) { LOG(INFO) << "Unable to get IPv" << (family == AF_INET ? "4" : "6") @@ -1253,15 +1252,25 @@ int main(int argc, char **argv) } } - char hostport[NI_MAXHOST+16]; bool downstream_ipv6_addr = is_ipv6_numeric_addr(get_config()->downstream_host); - snprintf(hostport, sizeof(hostport), "%s%s%s:%u", - downstream_ipv6_addr ? "[" : "", - get_config()->downstream_host, - downstream_ipv6_addr ? "]" : "", - get_config()->downstream_port); - set_config_str(&mod_config()->downstream_hostport, hostport); + + std::string hostport; + + if(downstream_ipv6_addr) { + hostport += "["; + } + + hostport += get_config()->downstream_host; + + if(downstream_ipv6_addr) { + hostport += "]"; + } + + hostport += ":"; + hostport += util::utos(get_config()->downstream_port); + + set_config_str(&mod_config()->downstream_hostport, hostport.c_str()); if(LOG_ENABLED(INFO)) { LOG(INFO) << "Resolving backend address"; diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index a4d35b8c..4a895bff 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -258,36 +258,37 @@ int HttpDownstreamConnection::push_request_headers() int HttpDownstreamConnection::push_upload_data_chunk (const uint8_t *data, size_t datalen) { - ssize_t res = 0; int rv; int chunked = downstream_->get_chunked_request(); auto output = bufferevent_get_output(bev_); + if(chunked) { - char chunk_size_hex[16]; - rv = snprintf(chunk_size_hex, sizeof(chunk_size_hex), "%X\r\n", - static_cast(datalen)); - res += rv; - rv = evbuffer_add(output, chunk_size_hex, rv); + auto chunk_size_hex = util::utox(datalen); + chunk_size_hex += "\r\n"; + + rv = evbuffer_add(output, chunk_size_hex.c_str(), chunk_size_hex.size()); if(rv == -1) { DCLOG(FATAL, this) << "evbuffer_add() failed"; return -1; } } + rv = evbuffer_add(output, data, datalen); + if(rv == -1) { DCLOG(FATAL, this) << "evbuffer_add() failed"; return -1; } - res += rv; + if(chunked) { rv = evbuffer_add(output, "\r\n", 2); if(rv == -1) { DCLOG(FATAL, this) << "evbuffer_add() failed"; return -1; } - res += 2; } - return res; + + return 0; } int HttpDownstreamConnection::end_upload_data() diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 45e01e73..6a00f3be 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -650,11 +650,12 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) if(LOG_ENABLED(INFO)) { DLOG(INFO, downstream) << "HTTP response header completed"; } - char temp[16]; - snprintf(temp, sizeof(temp), "HTTP/%d.%d ", - downstream->get_request_major(), - downstream->get_request_minor()); - std::string hdrs = temp; + + std::string hdrs = "HTTP/"; + hdrs += util::utos(downstream->get_request_major()); + hdrs += "."; + hdrs += util::utos(downstream->get_request_minor()); + hdrs += " "; hdrs += http2::get_status_string(downstream->get_response_http_status()); hdrs += "\r\n"; downstream->normalize_response_headers(); @@ -757,10 +758,12 @@ int HttpsUpstream::on_downstream_body(Downstream *downstream, } auto output = bufferevent_get_output(handler_->get_bev()); if(downstream->get_chunked_response()) { - char chunk_size_hex[16]; - rv = snprintf(chunk_size_hex, sizeof(chunk_size_hex), "%X\r\n", - static_cast(len)); - if(evbuffer_add(output, chunk_size_hex, rv) != 0) { + auto chunk_size_hex = util::utox(len); + chunk_size_hex += "\r\n"; + + rv = evbuffer_add(output, chunk_size_hex.c_str(), chunk_size_hex.size()); + + if(rv != 0) { ULOG(FATAL, this) << "evbuffer_add() failed"; return -1; } diff --git a/src/util.cc b/src/util.cc index e5440836..8b5f418a 100644 --- a/src/util.cc +++ b/src/util.cc @@ -42,6 +42,8 @@ namespace util { const char DEFAULT_STRIP_CHARSET[] = "\r\n\t "; +const char UPPER_XDIGITS[] = "0123456789ABCDEF"; + bool isAlpha(const char c) { return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'); @@ -68,13 +70,14 @@ std::string percentEncode(const unsigned char* target, size_t len) { std::string dest; for(size_t i = 0; i < len; ++i) { - if(inRFC3986UnreservedChars(target[i])) { - dest += target[i]; + unsigned char c = target[i]; + + if(inRFC3986UnreservedChars(c)) { + dest += c; } else { - char temp[4]; - snprintf(temp, sizeof(temp), "%%%02X", target[i]); - dest.append(temp); - //dest.append(fmt("%%%02X", target[i])); + dest += "%"; + dest += UPPER_XDIGITS[c >> 4]; + dest += UPPER_XDIGITS[(c & 0x0f)]; } } return dest; @@ -102,13 +105,14 @@ std::string percent_encode_token(const std::string& target) std::string dest; for(size_t i = 0; i < len; ++i) { - char c = target[i]; + unsigned char c = target[i]; + if(c != '%' && in_token(c)) { dest += c; } else { - char temp[4]; - snprintf(temp, sizeof(temp), "%%%02X", c); - dest += temp; + dest += "%"; + dest += UPPER_XDIGITS[c >> 4]; + dest += UPPER_XDIGITS[(c & 0x0f)]; } } return dest; diff --git a/src/util.h b/src/util.h index bdd39402..2c5f9362 100644 --- a/src/util.h +++ b/src/util.h @@ -399,6 +399,27 @@ std::string utos(T n) return res; } +extern const char UPPER_XDIGITS[]; + +template +std::string utox(T n) +{ + std::string res; + if(n == 0) { + res = "0"; + return res; + } + int i = 0; + T t = n; + for(; t; t /= 16, ++i); + res.resize(i); + --i; + for(; n; --i, n /= 16) { + res[i] = UPPER_XDIGITS[(n & 0x0f)]; + } + return res; +} + template typename std::enable_if::value, std::unique_ptr>::type make_unique(U&&... u) diff --git a/src/util_test.cc b/src/util_test.cc index c18f9ebf..3556f164 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -101,4 +101,14 @@ void test_util_percent_encode_token(void) CU_ASSERT("http%202" == util::percent_encode_token("http 2")); } +void test_util_utox(void) +{ + CU_ASSERT("0" == util::utox(0)); + CU_ASSERT("1" == util::utox(1)); + CU_ASSERT("F" == util::utox(15)); + CU_ASSERT("10" == util::utox(16)); + CU_ASSERT("3B9ACA07" == util::utox(1000000007)); + CU_ASSERT("100000000" == util::utox(1LL << 32)); +} + } // namespace shrpx diff --git a/src/util_test.h b/src/util_test.h index 7fd1686a..8a85ee89 100644 --- a/src/util_test.h +++ b/src/util_test.h @@ -32,6 +32,7 @@ void test_util_strieq(void); void test_util_inp_strlower(void); void test_util_to_base64(void); void test_util_percent_encode_token(void); +void test_util_utox(void); } // namespace shrpx