diff --git a/src/buffer.c b/src/buffer.c index 6bf310dd..943d3386 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -64,7 +64,9 @@ void buffer_move(buffer * restrict b, buffer * restrict src) { /* make sure buffer is at least "size" big + 1 for '\0'. keep old data */ __attribute_cold__ -static void buffer_realloc(buffer * const b, const size_t len) { +__attribute_noinline__ +__attribute_returns_nonnull__ +static char* buffer_realloc(buffer * const restrict b, const size_t len) { #define BUFFER_PIECE_SIZE 64uL /*(must be power-of-2)*/ const size_t sz = (len + 1 + BUFFER_PIECE_SIZE-1) & ~(BUFFER_PIECE_SIZE-1); force_assert(sz > len); @@ -73,60 +75,80 @@ static void buffer_realloc(buffer * const b, const size_t len) { b->ptr = realloc(b->ptr, sz); force_assert(NULL != b->ptr); + return b->ptr; } __attribute_cold__ __attribute_noinline__ -static void buffer_alloc_replace(buffer * const b, const size_t size) { - force_assert(NULL != b); +__attribute_returns_nonnull__ +static char* buffer_alloc_replace(buffer * const restrict b, const size_t size) { /*(discard old data so realloc() does not copy)*/ if (NULL != b->ptr) { free(b->ptr); b->ptr = NULL; } - buffer_realloc(b, size); + /*(note: if size larger than one lshift, use size instead of power-2)*/ + return buffer_realloc(b, (b->size << 1) > size ? (b->size << 1)-1 : size); } char* buffer_string_prepare_copy(buffer * const b, const size_t size) { - if (NULL == b->ptr || size >= b->size) buffer_alloc_replace(b, size); - - b->used = 0; - return b->ptr; + b->used = 0; + return (size < b->size) + ? b->ptr + : buffer_alloc_replace(b, size); } __attribute_cold__ __attribute_noinline__ __attribute_returns_nonnull__ -static char* buffer_string_prepare_append_resize(buffer * const b, const size_t size) { - force_assert(NULL != b); - if (buffer_string_is_empty(b)) { - return buffer_string_prepare_copy(b, size); - } else { - /* not empty, b->used already includes a terminating 0 */ - size_t req_size = b->used + size; +static char* buffer_string_prepare_append_resize(buffer * const restrict b, const size_t size) { + if (b->used < 2) /* buffer_string_is_empty(b) */ + return buffer_string_prepare_copy(b, size); - /* check for overflow: unsigned overflow is defined to wrap around */ - force_assert(req_size >= b->used); + /* not empty, b->used already includes a terminating 0 */ + /*(note: if size larger than one lshift, use size instead of power-2)*/ + const size_t req_size = ((b->size << 1) - b->used > size) + ? (b->size << 1)-1 + : b->used + size; - buffer_realloc(b, req_size); + /* check for overflow: unsigned overflow is defined to wrap around */ + force_assert(req_size >= b->used); - return b->ptr + b->used - 1; - } + return buffer_realloc(b, req_size) + b->used - 1; } char* buffer_string_prepare_append(buffer * const b, const size_t size) { - return (NULL != b->ptr && size < b->size - b->used) - ? b->ptr + b->used - (0 != b->used) + const uint32_t len = b->used ? b->used-1 : 0; + return (b->size - len >= size + 1) + ? b->ptr + len : buffer_string_prepare_append_resize(b, size); } -void buffer_string_set_length(buffer *b, uint32_t len) { - force_assert(NULL != b); - - if (len >= b->size) buffer_realloc(b, len); +/*(prefer smaller code than inlining buffer_extend in many places in buffer.c)*/ +__attribute_noinline__ +char* +buffer_extend (buffer * const b, const size_t x) +{ + /* extend buffer to append x (reallocate by power-2 (or larger), if needed) + * (combine buffer_string_prepare_append() and buffer_commit()) + * (future: might make buffer.h static inline func for HTTP/1.1 performance) + * pre-sets '\0' byte and b->used (unlike buffer_string_prepare_append())*/ + const uint32_t len = b->used ? b->used-1 : 0; + char * const s = (b->size - len >= x + 1) + ? b->ptr + len + : buffer_string_prepare_append_resize(b, x); + b->used = len+x+1; + s[x] = '\0'; + return s; +} - b->used = len + 1; - b->ptr[len] = '\0'; +void buffer_string_set_length(buffer *b, uint32_t len) { + /*(intended for string truncate; prefer buffer_extend() to extend string)*/ + /*(unlike others routines, this routine potentially extends string + * extra len + (up to) BUFFER_PIECE_SIZE without power-2 reallocation, + * but does not optimize realloc of empty string)*/ + b->used = len + 1; /*(not resizing for power-2)*/ + (len < b->size ? b->ptr : buffer_realloc(b, len))[len] = '\0'; } void buffer_commit(buffer *b, size_t size) @@ -151,12 +173,13 @@ void buffer_copy_string(buffer * restrict b, const char * restrict s) { buffer_copy_string_len(b, s, NULL != s ? strlen(s) : 0); } -void buffer_copy_string_len(buffer * const restrict b, const char * const restrict s, const size_t s_len) { - if (NULL == b->ptr || s_len >= b->size) buffer_alloc_replace(b, s_len); - - b->used = s_len + 1; - b->ptr[s_len] = '\0'; - if (0 != s_len) memcpy(b->ptr, s, s_len); /*(s might be NULL)*/ +void buffer_copy_string_len(buffer * const restrict b, const char * const restrict s, const size_t len) { + b->used = len + 1; + char * const restrict d = (len < b->size) + ? b->ptr + : buffer_alloc_replace(b, len); + d[len] = '\0'; + memcpy(d, s, len); } void buffer_append_string(buffer * restrict b, const char * restrict s) { @@ -174,28 +197,29 @@ void buffer_append_string(buffer * restrict b, const char * restrict s) { * @param s_len size of the string (without the terminating \0) */ -void buffer_append_string_len(buffer * const restrict b, const char * const restrict s, const size_t s_len) { - char * const target_buf = buffer_string_prepare_append(b, s_len); - b->used += s_len + (0 == b->used); /*(must include '\0' for append)*/ - target_buf[s_len] = '\0'; - - /*(s might be NULL if 0 == s_len)*/ - if (s_len) memcpy(target_buf, s, s_len); +void buffer_append_string_len(buffer * const restrict b, const char * const restrict s, const size_t len) { + memcpy(buffer_extend(b, len), s, len); } void buffer_append_path_len(buffer * restrict b, const char * restrict a, size_t alen) { - size_t blen = buffer_string_length(b); - int aslash = (alen && a[0] == '/'); - buffer_string_prepare_append(b, alen+2); /*(+ '/' and + '\0' if 0 == blen)*/ - if (blen && b->ptr[blen-1] == '/') { - if (aslash) --b->used; + char * restrict s = buffer_string_prepare_append(b, alen+1); + const int aslash = (alen && a[0] == '/'); + if (b->used > 1 && s[-1] == '/') { + if (aslash) { + ++a; + --alen; + } } else { - if (!b->used) ++b->used; - if (!aslash) b->ptr[++b->used - 2] = '/'; + if (0 == b->used) b->used = 1; + if (!aslash) { + *s++ = '/'; + ++b->used; + } } - memcpy(b->ptr+b->used-1, a, alen); - b->ptr[(b->used += alen)-1] = '\0'; + b->used += alen; + s[alen] = '\0'; + memcpy(s, a, alen); } void buffer_append_uint_hex_lc(buffer *b, uintmax_t value) { @@ -210,8 +234,7 @@ void buffer_append_uint_hex_lc(buffer *b, uintmax_t value) { } while (0 != copy); } - buf = buffer_string_prepare_append(b, shift >> 2); /*nibbles (4 bits)*/ - buffer_commit(b, shift >> 2); /* will fill below */ + buf = buffer_extend(b, shift >> 2); /*nibbles (4 bits)*/ while (shift > 0) { shift -= 4; @@ -425,9 +448,7 @@ void buffer_substr_replace (buffer * const restrict b, const size_t offset, void buffer_append_string_encoded_hex_lc(buffer * const restrict b, const char * const restrict s, size_t len) { - unsigned char * const p = - (unsigned char*) buffer_string_prepare_append(b, len*2); - buffer_commit(b, len*2); /* fill below */ + unsigned char * const p = (unsigned char *)buffer_extend(b, len*2); for (size_t i = 0; i < len; ++i) { p[(i<<1)] = hex_chars_lc[(s[i] >> 4) & 0x0F]; p[(i<<1)+1] = hex_chars_lc[(s[i]) & 0x0F]; @@ -435,9 +456,7 @@ void buffer_append_string_encoded_hex_lc(buffer * const restrict b, const char * } void buffer_append_string_encoded_hex_uc(buffer * const restrict b, const char * const restrict s, size_t len) { - unsigned char * const p = - (unsigned char*) buffer_string_prepare_append(b, len*2); - buffer_commit(b, len*2); /* fill below */ + unsigned char * const p = (unsigned char *)buffer_extend(b, len*2); for (size_t i = 0; i < len; ++i) { p[(i<<1)] = hex_chars_uc[(s[i] >> 4) & 0x0F]; p[(i<<1)+1] = hex_chars_uc[(s[i]) & 0x0F]; @@ -581,8 +600,7 @@ void buffer_append_string_encoded(buffer * const restrict b, const char * const } } - d = (unsigned char*) buffer_string_prepare_append(b, d_len); - buffer_commit(b, d_len); /* fill below */ + d = (unsigned char*) buffer_extend(b, d_len); for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { if (map[*ds & 0xFF]) { @@ -636,8 +654,7 @@ void buffer_append_string_c_escaped(buffer * const restrict b, const char * cons } } - d = (unsigned char*) buffer_string_prepare_append(b, d_len); - buffer_commit(b, d_len); /* fill below */ + d = (unsigned char*) buffer_extend(b, d_len); for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { if ((*ds < 0x20) /* control character */ diff --git a/src/buffer.h b/src/buffer.h index d055c085..2a5bb4dc 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -62,6 +62,13 @@ char* buffer_string_prepare_copy(buffer *b, size_t size); __attribute_returns_nonnull__ char* buffer_string_prepare_append(buffer *b, size_t size); +/* extend and modify buffer for immediate addition of x bytes (differs from + * buffer_string_prepare_append() which only ensures space is available) + * returns pointer to which callers should immediately write x bytes + */ +__attribute_returns_nonnull__ +char* buffer_extend(buffer * const restrict b, size_t x); + /* use after prepare_(copy,append) when you have written data to the buffer * to increase the buffer length by size. also sets the terminating zero. * requires enough space is present for the terminating zero (prepare with the @@ -99,11 +106,11 @@ __attribute_cold__ void buffer_free_ptr(buffer *b); void buffer_copy_string(buffer * restrict b, const char * restrict s); -void buffer_copy_string_len(buffer * restrict b, const char * restrict s, size_t s_len); +void buffer_copy_string_len(buffer * restrict b, const char * restrict s, size_t len); static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src); void buffer_append_string(buffer * restrict b, const char * restrict s); -void buffer_append_string_len(buffer * restrict b, const char * restrict s, size_t s_len); +void buffer_append_string_len(buffer * restrict b, const char * restrict s, size_t len); static inline void buffer_append_string_buffer(buffer * restrict b, const buffer * restrict src); #define buffer_append_uint_hex(b,len) buffer_append_uint_hex_lc((b),(len)) diff --git a/src/log.c b/src/log.c index d27ececf..94b18afb 100644 --- a/src/log.c +++ b/src/log.c @@ -152,8 +152,8 @@ log_buffer_vprintf (buffer * const b, va_end(aptry); if (n >= bsp) { - buffer_string_prepare_append(b, n); /*(must re-read s after realloc)*/ - vsnprintf((s = b->ptr + blen), buffer_string_space(b)+1, fmt, ap); + s = buffer_extend(b, n); + vsnprintf(s, n+1, fmt, ap); } size_t i; diff --git a/src/mod_authn_ldap.c b/src/mod_authn_ldap.c index 5da14e25..bbed1547 100644 --- a/src/mod_authn_ldap.c +++ b/src/mod_authn_ldap.c @@ -409,12 +409,10 @@ static void mod_authn_append_ldap_dn_escape(buffer * const filter, const buffer else { /* escape NUL ('\0') (and all UTF-8 chars with high bit set) */ char *f; - buffer_string_prepare_append(filter, 3); - f = filter->ptr + buffer_string_length(filter); + f = buffer_extend(filter, 3); f[0] = '\\'; f[1] = "0123456789abcdef"[(((unsigned char *)b)[i] >> 4) & 0xf]; f[2] = "0123456789abcdef"[(((unsigned char *)b)[i] ) & 0xf]; - buffer_commit(filter, 3); } } @@ -481,12 +479,10 @@ static void mod_authn_append_ldap_filter_escape(buffer * const filter, const buf } /* escape * ( ) \ NUL ('\0') (and all UTF-8 chars with high bit set) */ - buffer_string_prepare_append(filter, 3); - f = filter->ptr + buffer_string_length(filter); + f = buffer_extend(filter, 3); f[0] = '\\'; f[1] = "0123456789abcdef"[(((unsigned char *)b)[i] >> 4) & 0xf]; f[2] = "0123456789abcdef"[(((unsigned char *)b)[i] ) & 0xf]; - buffer_commit(filter, 3); } } diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 01c60576..f761756b 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -137,25 +137,11 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { static int fcgi_env_add(void *venv, const char *key, size_t key_len, const char *val, size_t val_len) { buffer *env = venv; - size_t len; char len_enc[8]; size_t len_enc_len = 0; - char *dst; if (!key || (!val && val_len)) return -1; - len = key_len + val_len; - - len += key_len > 127 ? 4 : 1; - len += val_len > 127 ? 4 : 1; - - if (buffer_string_length(env) + len >= FCGI_MAX_LENGTH + sizeof(FCGI_BeginRequestRecord) + sizeof(FCGI_Header)) { - /** - * we can't append more headers, ignore it - */ - return -1; - } - /** * field length can be 31bit max * @@ -164,35 +150,31 @@ static int fcgi_env_add(void *venv, const char *key, size_t key_len, const char force_assert(key_len < 0x7fffffffu); force_assert(val_len < 0x7fffffffu); - if (buffer_string_space(env) < len) { - size_t extend = env->size * 2 - buffer_string_length(env); - extend = extend > len ? extend : len + 4095; - buffer_string_prepare_append(env, extend); - } - if (key_len > 127) { - len_enc[len_enc_len++] = ((key_len >> 24) & 0xff) | 0x80; - len_enc[len_enc_len++] = (key_len >> 16) & 0xff; - len_enc[len_enc_len++] = (key_len >> 8) & 0xff; - len_enc[len_enc_len++] = (key_len >> 0) & 0xff; - } else { - len_enc[len_enc_len++] = (key_len >> 0) & 0xff; + len_enc[0] = ((key_len >> 24) & 0xff) | 0x80; + len_enc[1] = (key_len >> 16) & 0xff; + len_enc[2] = (key_len >> 8) & 0xff; + len_enc_len += 3; } + len_enc[len_enc_len++] = key_len & 0xff; if (val_len > 127) { len_enc[len_enc_len++] = ((val_len >> 24) & 0xff) | 0x80; len_enc[len_enc_len++] = (val_len >> 16) & 0xff; len_enc[len_enc_len++] = (val_len >> 8) & 0xff; - len_enc[len_enc_len++] = (val_len >> 0) & 0xff; - } else { - len_enc[len_enc_len++] = (val_len >> 0) & 0xff; } + len_enc[len_enc_len++] = val_len & 0xff; + + const size_t len = len_enc_len + key_len + val_len; + const size_t fmax = + FCGI_MAX_LENGTH + sizeof(FCGI_BeginRequestRecord) + sizeof(FCGI_Header); + if (buffer_string_length(env) + len >= fmax) + return -1; /* we can't append more headers, ignore it */ - dst = buffer_string_prepare_append(env, len); + char * const dst = buffer_extend(env, len); memcpy(dst, len_enc, len_enc_len); memcpy(dst + len_enc_len, key, key_len); if (val_len) memcpy(dst + len_enc_len + key_len, val, val_len); - buffer_commit(env, len); return 0; } diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 3dbb4391..eb626456 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -869,26 +869,24 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { http_header_remap_uri(b, buffer_string_length(b) - buffer_string_length(&r->target), &hctx->conf.header, 1); if (!hctx->conf.header.force_http10) - buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.1\r\n")); + buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.1")); else - buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.0\r\n")); + buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.0")); if (hctx->conf.replace_http_host && !buffer_string_is_empty(hctx->gw.host->id)) { if (hctx->gw.conf.debug > 1) { log_error(r->conf.errh, __FILE__, __LINE__, "proxy - using \"%s\" as HTTP Host", hctx->gw.host->id->ptr); } - buffer_append_string_len(b, CONST_STR_LEN("Host: ")); + buffer_append_string_len(b, CONST_STR_LEN("\r\nHost: ")); buffer_append_string_buffer(b, hctx->gw.host->id); - buffer_append_string_len(b, CONST_STR_LEN("\r\n")); } else if (!buffer_string_is_empty(r->http_host)) { - buffer_append_string_len(b, CONST_STR_LEN("Host: ")); + buffer_append_string_len(b, CONST_STR_LEN("\r\nHost: ")); buffer_append_string_buffer(b, r->http_host); if (remap_headers) { size_t alen = buffer_string_length(r->http_host); http_header_remap_host(b, buffer_string_length(b) - alen, &hctx->conf.header, 1, alen); } - buffer_append_string_len(b, CONST_STR_LEN("\r\n")); } /* "Forwarded" and legacy X- headers */ @@ -911,7 +909,7 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { && (r->conf.stream_request_body & (FDEVENT_STREAM_REQUEST | FDEVENT_STREAM_REQUEST_BUFMIN))) { hctx->gw.stdin_append = proxy_stdin_append; /* stream chunked body */ - buffer_append_string_len(b, CONST_STR_LEN("Transfer-Encoding: chunked\r\n")); + buffer_append_string_len(b, CONST_STR_LEN("\r\nTransfer-Encoding: chunked")); } /* request header */ @@ -957,17 +955,14 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { const uint32_t klen = buffer_string_length(&ds->key); const uint32_t vlen = buffer_string_length(&ds->value); if (0 == klen || 0 == vlen) continue; - - if (buffer_string_space(b) < klen + vlen + 4) { - size_t extend = b->size * 2 - buffer_string_length(b); - extend = extend > klen + vlen + 4 ? extend : klen + vlen + 4 + 4095; - buffer_string_prepare_append(b, extend); - } - - buffer_append_string_len(b, ds->key.ptr, klen); - buffer_append_string_len(b, CONST_STR_LEN(": ")); - buffer_append_string_len(b, ds->value.ptr, vlen); - buffer_append_string_len(b, CONST_STR_LEN("\r\n")); + char * restrict s = buffer_extend(b, klen+vlen+4); + s[0] = '\r'; + s[1] = '\n'; + memcpy(s+2, ds->key.ptr, klen); + s += 2+klen; + s[0] = ':'; + s[1] = ' '; + memcpy(s+2, ds->value.ptr, vlen); if (!remap_headers) continue; @@ -994,13 +989,13 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { continue; } - http_header_remap_uri(b, buffer_string_length(b) - vlen - 2, &hctx->conf.header, 1); + http_header_remap_uri(b, buffer_string_length(b) - vlen, &hctx->conf.header, 1); } if (connhdr && !hctx->conf.header.force_http10 && r->http_version >= HTTP_VERSION_1_1 && !buffer_eq_icase_slen(connhdr, CONST_STR_LEN("close"))) { /* mod_proxy always sends Connection: close to backend */ - buffer_append_string_len(b, CONST_STR_LEN("Connection: close")); + buffer_append_string_len(b, CONST_STR_LEN("\r\nConnection: close")); /* (future: might be pedantic and also check Connection header for each * token using http_header_str_contains_token() */ if (!buffer_string_is_empty(te)) @@ -1010,7 +1005,7 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n")); } else /* mod_proxy always sends Connection: close to backend */ - buffer_append_string_len(b, CONST_STR_LEN("Connection: close\r\n\r\n")); + buffer_append_string_len(b, CONST_STR_LEN("\r\nConnection: close\r\n\r\n")); hctx->gw.wb_reqlen = buffer_string_length(b); chunkqueue_prepend_buffer_commit(&hctx->gw.wb); diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 18b618cc..70cf00b8 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -16,8 +16,6 @@ typedef gw_handler_ctx handler_ctx; #include "log.h" #include "status_counter.h" -#include "sys-endian.h" - enum { LI_PROTOCOL_SCGI, LI_PROTOCOL_UWSGI }; static void mod_scgi_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) { @@ -147,62 +145,35 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { static int scgi_env_add_scgi(void *venv, const char *key, size_t key_len, const char *val, size_t val_len) { buffer *env = venv; - char *dst; size_t len; if (!key || (!val && val_len)) return -1; len = key_len + val_len + 2; - if (buffer_string_space(env) < len) { - size_t extend = env->size * 2 - buffer_string_length(env); - extend = extend > len ? extend : len + 4095; - buffer_string_prepare_append(env, extend); - } - - dst = buffer_string_prepare_append(env, len); + char *dst = buffer_extend(env, len); memcpy(dst, key, key_len); dst[key_len] = '\0'; - memcpy(dst + key_len + 1, val, val_len); - dst[key_len + 1 + val_len] = '\0'; - buffer_commit(env, len); + dst += key_len + 1; + memcpy(dst, val, val_len); + dst[val_len] = '\0'; return 0; } -#ifdef __LITTLE_ENDIAN__ -#define uwsgi_htole16(x) (x) -#else /* __BIG_ENDIAN__ */ -#define uwsgi_htole16(x) ((uint16_t) (((x) & 0xff) << 8 | ((x) & 0xff00) >> 8)) -#endif - - static int scgi_env_add_uwsgi(void *venv, const char *key, size_t key_len, const char *val, size_t val_len) { - buffer *env = venv; - char *dst; - size_t len; - uint16_t uwlen; - if (!key || (!val && val_len)) return -1; if (key_len > USHRT_MAX || val_len > USHRT_MAX) return -1; - len = 2 + key_len + 2 + val_len; - - if (buffer_string_space(env) < len) { - size_t extend = env->size * 2 - buffer_string_length(env); - extend = extend > len ? extend : len + 4095; - buffer_string_prepare_append(env, extend); - } - - dst = buffer_string_prepare_append(env, len); - uwlen = uwsgi_htole16((uint16_t)key_len); - memcpy(dst, (char *)&uwlen, 2); + char *dst = buffer_extend(venv, 2 + key_len + 2 + val_len); + dst[0] = key_len & 0xff; /* little-endian */ + dst[1] = (key_len >> 8) & 0xff; memcpy(dst + 2, key, key_len); - uwlen = uwsgi_htole16((uint16_t)val_len); - memcpy(dst + 2 + key_len, (char *)&uwlen, 2); - memcpy(dst + 2 + key_len + 2, val, val_len); - buffer_commit(env, len); + dst += 2+key_len; + dst[0] = val_len & 0xff; /* little-endian */ + dst[1] = (val_len >> 8) & 0xff; + memcpy(dst + 2, val, val_len); return 0; } @@ -246,7 +217,6 @@ static handler_t scgi_create_env(handler_ctx *hctx) { } else { /* LI_PROTOCOL_UWSGI */ /* http://uwsgi-docs.readthedocs.io/en/latest/Protocol.html */ size_t len = buffer_string_length(b)-10; - uint32_t uwsgi_header; if (len > USHRT_MAX) { r->http_status = 431; /* Request Header Fields Too Large */ r->handler_module = NULL; @@ -255,8 +225,10 @@ static handler_t scgi_create_env(handler_ctx *hctx) { return HANDLER_FINISHED; } offset = 10 - 4; - uwsgi_header = ((uint32_t)uwsgi_htole16((uint16_t)len)) << 8; - memcpy(b->ptr+offset, (char *)&uwsgi_header, 4); + b->ptr[offset] = 0; + b->ptr[offset+1] = len & 0xff; /* little-endian */ + b->ptr[offset+2] = (len >> 8) & 0xff; + b->ptr[offset+3] = 0; } hctx->wb_reqlen = buffer_string_length(b) - offset; diff --git a/src/mod_vhostdb_ldap.c b/src/mod_vhostdb_ldap.c index a8fd2299..e0b8737b 100644 --- a/src/mod_vhostdb_ldap.c +++ b/src/mod_vhostdb_ldap.c @@ -242,12 +242,10 @@ static void mod_authn_append_ldap_filter_escape(buffer * const filter, const buf } /* escape * ( ) \ NUL ('\0') (and all UTF-8 chars with high bit set) */ - buffer_string_prepare_append(filter, 3); - f = filter->ptr + buffer_string_length(filter); + f = buffer_extend(filter, 3); f[0] = '\\'; f[1] = "0123456789abcdef"[(((unsigned char *)b)[i] >> 4) & 0xf]; f[2] = "0123456789abcdef"[(((unsigned char *)b)[i] ) & 0xf]; - buffer_commit(filter, 3); } } diff --git a/src/response.c b/src/response.c index 2ef00032..721e47cd 100644 --- a/src/response.c +++ b/src/response.c @@ -118,16 +118,20 @@ http_response_write_header (request_st * const r) /* add all headers */ for (size_t i = 0; i < r->resp_headers.used; ++i) { const data_string * const ds = (data_string *)r->resp_headers.data[i]; - - if (buffer_string_is_empty(&ds->value)) continue; - if (buffer_string_is_empty(&ds->key)) continue; + const uint32_t klen = buffer_string_length(&ds->key); + const uint32_t vlen = buffer_string_length(&ds->value); + if (0 == klen || 0 == vlen) + continue; if ((ds->key.ptr[0] & 0xdf) == 'X' && http_response_omit_header(r, ds)) continue; - - buffer_append_string_len(b, CONST_STR_LEN("\r\n")); - buffer_append_string_buffer(b, &ds->key); - buffer_append_string_len(b, CONST_STR_LEN(": ")); - buffer_append_string_buffer(b, &ds->value); + char * restrict s = buffer_extend(b, klen+vlen+4); + s[0] = '\r'; + s[1] = '\n'; + memcpy(s+2, ds->key.ptr, klen); + s += 2+klen; + s[0] = ':'; + s[1] = ' '; + memcpy(s+2, ds->value.ptr, vlen); } if (!light_btst(r->resp_htags, HTTP_HEADER_DATE)) {