Browse Source

[multiple] reduce redundant NULL buffer checks

This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.

Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.

In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func.  In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.

- check for empty strings at config time and set value to NULL if blank
  string will be ignored at runtime; at runtime, simple pointer check
  for NULL can be used to check for a value that has been set and is not
  blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
  and use buffer_is_unset() instead of buffer_is_empty(),
  where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
  known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
  truncate string, and use buffer_extend() to extend

Examples where buffer known not to be NULL:
  - cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
    (though we might set it to NULL if buffer_is_blank(cpv->v.b))
  - address of buffer is arg (&foo)
    (compiler optimizer detects this in most, but not all, cases)
  - buffer is checked for NULL earlier in func
  - buffer is accessed in same scope without a NULL check (e.g. b->ptr)

internal behavior change:
  callers must not pass a NULL buffer to some funcs.
  - buffer_init_buffer() requires non-null args
  - buffer_copy_buffer() requires non-null args
  - buffer_append_string_buffer() requires non-null args
  - buffer_string_space() requires non-null arg
master
Glenn Strauss 5 months ago
parent
commit
af3df29ae8
  1. 64
      src/array.c
  2. 58
      src/buffer.c
  3. 170
      src/buffer.h
  4. 36
      src/burl.c
  5. 67
      src/chunk.c
  6. 6
      src/configfile-glue.c
  7. 104
      src/configfile.c
  8. 42
      src/configparser.y
  9. 24
      src/connections.c
  10. 2
      src/data_config.c
  11. 181
      src/gw_backend.c
  12. 56
      src/h2.c
  13. 46
      src/http-header-glue.c
  14. 81
      src/http_cgi.c
  15. 22
      src/http_chunk.c
  16. 14
      src/http_etag.c
  17. 12
      src/http_header.c
  18. 10
      src/http_range.c
  19. 42
      src/keyvalue.c
  20. 18
      src/log.c
  21. 88
      src/mod_accesslog.c
  22. 27
      src/mod_ajp13.c
  23. 14
      src/mod_alias.c
  24. 36
      src/mod_auth.c
  25. 11
      src/mod_authn_dbi.c
  26. 37
      src/mod_authn_file.c
  27. 65
      src/mod_authn_gssapi.c
  28. 26
      src/mod_authn_ldap.c
  29. 6
      src/mod_authn_mysql.c
  30. 23
      src/mod_authn_sasl.c
  31. 14
      src/mod_cgi.c
  32. 26
      src/mod_cml.c
  33. 36
      src/mod_cml_lua.c
  34. 45
      src/mod_deflate.c
  35. 82
      src/mod_dirlisting.c
  36. 25
      src/mod_evasive.c
  37. 14
      src/mod_evhost.c
  38. 11
      src/mod_expire.c
  39. 45
      src/mod_extforward.c
  40. 12
      src/mod_fastcgi.c
  41. 4
      src/mod_flv_streaming.c
  42. 2
      src/mod_geoip.c
  43. 74
      src/mod_gnutls.c
  44. 9
      src/mod_indexfile.c
  45. 46
      src/mod_magnet.c
  46. 6
      src/mod_magnet_cache.c
  47. 11
      src/mod_maxminddb.c
  48. 63
      src/mod_mbedtls.c
  49. 32
      src/mod_mysql_vhost.c
  50. 61
      src/mod_nss.c
  51. 98
      src/mod_openssl.c
  52. 108
      src/mod_proxy.c
  53. 4
      src/mod_redirect.c
  54. 4
      src/mod_rewrite.c
  55. 12
      src/mod_rrdtool.c
  56. 8
      src/mod_scgi.c
  57. 31
      src/mod_secdownload.c
  58. 34
      src/mod_setenv.c
  59. 22
      src/mod_simple_vhost.c
  60. 2
      src/mod_skeleton.c
  61. 88
      src/mod_ssi.c
  62. 6
      src/mod_ssi_expr.c
  63. 4
      src/mod_staticfile.c
  64. 109
      src/mod_status.c
  65. 22
      src/mod_trigger_b4_dl.c
  66. 28
      src/mod_uploadprogress.c
  67. 37
      src/mod_userdir.c
  68. 35
      src/mod_usertrack.c
  69. 20
      src/mod_vhostdb.c
  70. 10
      src/mod_vhostdb_dbi.c
  71. 19
      src/mod_vhostdb_ldap.c
  72. 15
      src/mod_vhostdb_mysql.c
  73. 11
      src/mod_vhostdb_pgsql.c
  74. 180
      src/mod_webdav.c
  75. 126
      src/mod_wolfssl.c
  76. 47
      src/mod_wstunnel.c
  77. 19
      src/network.c
  78. 6
      src/network_write.c
  79. 6
      src/plugin.c
  80. 2
      src/reqpool.c
  81. 42
      src/request.c
  82. 67
      src/response.c
  83. 20
      src/server.c
  84. 6
      src/sock_addr.c
  85. 6
      src/sock_addr_cache.c
  86. 48
      src/stat_cache.c

64
src/array.c

@ -12,7 +12,7 @@ __attribute_cold__
static data_unset *array_data_string_copy(const data_unset *s) {
data_string *src = (data_string *)s;
data_string *ds = array_data_string_init();
if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&ds->key, &src->key);
if (!buffer_is_unset(&src->key)) buffer_copy_buffer(&ds->key, &src->key);
buffer_copy_buffer(&ds->value, &src->value);
return (data_unset *)ds;
}
@ -21,9 +21,9 @@ __attribute_cold__
static void array_data_string_insert_dup(data_unset *dst, data_unset *src) {
data_string *ds_dst = (data_string *)dst;
data_string *ds_src = (data_string *)src;
if (!buffer_is_empty(&ds_dst->value))
if (!buffer_is_blank(&ds_dst->value))
buffer_append_str2(&ds_dst->value, CONST_STR_LEN(", "),
CONST_BUF_LEN(&ds_src->value));
BUF_PTR_LEN(&ds_src->value));
else
buffer_copy_buffer(&ds_dst->value, &ds_src->value);
}
@ -54,7 +54,7 @@ __attribute_cold__
static data_unset *array_data_integer_copy(const data_unset *s) {
data_integer *src = (data_integer *)s;
data_integer *di = array_data_integer_init();
if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&di->key, &src->key);
if (!buffer_is_unset(&src->key)) buffer_copy_buffer(&di->key, &src->key);
di->value = src->value;
return (data_unset *)di;
}
@ -84,7 +84,7 @@ __attribute_cold__
static data_unset *array_data_array_copy(const data_unset *s) {
data_array *src = (data_array *)s;
data_array *da = array_data_array_init();
if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&da->key, &src->key);
if (!buffer_is_unset(&src->key)) buffer_copy_buffer(&da->key, &src->key);
array_copy_array(&da->value, &src->value);
return (data_unset *)da;
}
@ -221,7 +221,7 @@ static int array_keycmpb(const char * const k, const uint32_t klen, const buffer
* if inserted into key-value array */
/*force_assert(b && b->used);*/
return array_keycmp(k, klen, b->ptr, b->used-1);
/*return array_keycmp(k, klen, CONST_BUF_LEN(b));*/
/*return array_keycmp(k, klen, BUF_PTR_LEN(b));*/
}
/* returns pos into a->sorted[] which contains copy of data (ptr) in a->data[]
@ -276,7 +276,7 @@ static int32_t array_get_index(const array * const a, const char * const k, cons
* if inserted into key-value array */
/*force_assert(b && b->used);*/
int cmp = array_keycmp(k, klen, b->ptr, b->used-1);
/*int cmp = array_keycmp(k, klen, CONST_BUF_LEN(b));*/
/*int cmp = array_keycmp(k, klen, BUF_PTR_LEN(b));*/
if (cmp < 0) /* key < [probe] */
upper = probe; /* still: lower <= upper */
else if (cmp > 0) /* key > [probe] */
@ -436,13 +436,13 @@ static data_unset **array_find_or_insert(array * const a, data_unset * const ent
force_assert(NULL != entry);
/* push value onto end of array if there is no key */
if (buffer_is_empty(&entry->key)) {
if (buffer_is_unset(&entry->key)) {
array_insert_data_at_pos(a, entry, a->used);
return NULL;
}
/* try to find the entry */
const int32_t ipos = array_get_index(a, CONST_BUF_LEN(&entry->key));
const int32_t ipos = array_get_index(a, BUF_PTR_LEN(&entry->key));
if (ipos >= 0) return &a->sorted[ipos];
array_insert_data_at_pos(a, entry, (uint32_t)(-ipos - 1));
@ -454,7 +454,7 @@ void array_replace(array * const a, data_unset * const entry) {
if (NULL == array_find_or_insert(a, entry)) return;
/* find the entry (array_find_or_insert() returned non-NULL) */
const int32_t ipos = array_get_index(a, CONST_BUF_LEN(&entry->key));
const int32_t ipos = array_get_index(a, BUF_PTR_LEN(&entry->key));
force_assert(ipos >= 0);
data_unset *old = a->sorted[ipos];
force_assert(old != entry);
@ -483,7 +483,7 @@ void array_insert_unique(array * const a, data_unset * const entry) {
int array_is_vlist(const array * const a) {
for (uint32_t i = 0; i < a->used; ++i) {
data_unset *du = a->data[i];
if (!buffer_is_empty(&du->key) || du->type != TYPE_STRING) return 0;
if (!buffer_is_unset(&du->key) || du->type != TYPE_STRING) return 0;
}
return 1;
}
@ -491,7 +491,7 @@ int array_is_vlist(const array * const a) {
int array_is_kvany(const array * const a) {
for (uint32_t i = 0; i < a->used; ++i) {
data_unset *du = a->data[i];
if (buffer_is_empty(&du->key)) return 0;
if (buffer_is_unset(&du->key)) return 0;
}
return 1;
}
@ -499,7 +499,7 @@ int array_is_kvany(const array * const a) {
int array_is_kvarray(const array * const a) {
for (uint32_t i = 0; i < a->used; ++i) {
data_unset *du = a->data[i];
if (buffer_is_empty(&du->key) || du->type != TYPE_ARRAY) return 0;
if (buffer_is_unset(&du->key) || du->type != TYPE_ARRAY) return 0;
}
return 1;
}
@ -507,7 +507,7 @@ int array_is_kvarray(const array * const a) {
int array_is_kvstring(const array * const a) {
for (uint32_t i = 0; i < a->used; ++i) {
data_unset *du = a->data[i];
if (buffer_is_empty(&du->key) || du->type != TYPE_STRING) return 0;
if (buffer_is_unset(&du->key) || du->type != TYPE_STRING) return 0;
}
return 1;
}
@ -523,7 +523,7 @@ array_match_key_prefix_klen (const array * const a, const char * const s, const
{
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const key = &a->data[i]->key;
const uint32_t klen = buffer_string_length(key);
const uint32_t klen = buffer_clen(key);
if (klen <= slen && 0 == memcmp(s, key->ptr, klen))
return a->data[i];
}
@ -535,7 +535,7 @@ array_match_key_prefix_nc_klen (const array * const a, const char * const s, con
{
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const key = &a->data[i]->key;
const uint32_t klen = buffer_string_length(key);
const uint32_t klen = buffer_clen(key);
if (klen <= slen && buffer_eq_icase_ssn(s, key->ptr, klen))
return a->data[i];
}
@ -548,23 +548,23 @@ array_match_key_prefix (const array * const a, const buffer * const b)
#ifdef __clang_analyzer__
force_assert(b);
#endif
return array_match_key_prefix_klen(a, CONST_BUF_LEN(b));
return array_match_key_prefix_klen(a, BUF_PTR_LEN(b));
}
data_unset *
array_match_key_prefix_nc (const array * const a, const buffer * const b)
{
return array_match_key_prefix_nc_klen(a, CONST_BUF_LEN(b));
return array_match_key_prefix_nc_klen(a, BUF_PTR_LEN(b));
}
const buffer *
array_match_value_prefix (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const value = &((data_string *)a->data[i])->value;
const uint32_t vlen = buffer_string_length(value);
const uint32_t vlen = buffer_clen(value);
if (vlen <= blen && 0 == memcmp(b->ptr, value->ptr, vlen))
return value;
}
@ -574,11 +574,11 @@ array_match_value_prefix (const array * const a, const buffer * const b)
const buffer *
array_match_value_prefix_nc (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const value = &((data_string *)a->data[i])->value;
const uint32_t vlen = buffer_string_length(value);
const uint32_t vlen = buffer_clen(value);
if (vlen <= blen && buffer_eq_icase_ssn(b->ptr, value->ptr, vlen))
return value;
}
@ -588,12 +588,12 @@ array_match_value_prefix_nc (const array * const a, const buffer * const b)
data_unset *
array_match_key_suffix (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
const char * const end = b->ptr + blen;
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const key = &a->data[i]->key;
const uint32_t klen = buffer_string_length(key);
const uint32_t klen = buffer_clen(key);
if (klen <= blen && 0 == memcmp(end - klen, key->ptr, klen))
return a->data[i];
}
@ -603,12 +603,12 @@ array_match_key_suffix (const array * const a, const buffer * const b)
data_unset *
array_match_key_suffix_nc (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
const char * const end = b->ptr + blen;
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const key = &a->data[i]->key;
const uint32_t klen = buffer_string_length(key);
const uint32_t klen = buffer_clen(key);
if (klen <= blen && buffer_eq_icase_ssn(end - klen, key->ptr, klen))
return a->data[i];
}
@ -618,12 +618,12 @@ array_match_key_suffix_nc (const array * const a, const buffer * const b)
const buffer *
array_match_value_suffix (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
const char * const end = b->ptr + blen;
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const value = &((data_string *)a->data[i])->value;
const uint32_t vlen = buffer_string_length(value);
const uint32_t vlen = buffer_clen(value);
if (vlen <= blen && 0 == memcmp(end - vlen, value->ptr, vlen))
return value;
}
@ -633,12 +633,12 @@ array_match_value_suffix (const array * const a, const buffer * const b)
const buffer *
array_match_value_suffix_nc (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
const char * const end = b->ptr + blen;
for (uint32_t i = 0; i < a->used; ++i) {
const buffer * const value = &((data_string *)a->data[i])->value;
const uint32_t vlen = buffer_string_length(value);
const uint32_t vlen = buffer_clen(value);
if (vlen <= blen && buffer_eq_icase_ssn(end - vlen, value->ptr, vlen))
return value;
}
@ -648,12 +648,12 @@ array_match_value_suffix_nc (const array * const a, const buffer * const b)
data_unset *
array_match_path_or_ext (const array * const a, const buffer * const b)
{
const uint32_t blen = buffer_string_length(b);
const uint32_t blen = buffer_clen(b);
for (uint32_t i = 0; i < a->used; ++i) {
/* check extension in the form "^/path" or ".ext$" */
const buffer * const key = &a->data[i]->key;
const uint32_t klen = buffer_string_length(key);
const uint32_t klen = buffer_clen(key);
if (klen <= blen
&& 0 == memcmp((*(key->ptr) == '/' ? b->ptr : b->ptr + blen - klen),
key->ptr, klen))

58
src/buffer.c

@ -14,27 +14,21 @@ static const char hex_chars_uc[] = "0123456789ABCDEF";
*
*/
__attribute_noinline__
buffer* buffer_init(void) {
buffer *b;
b = malloc(sizeof(*b));
buffer * const b = calloc(1, sizeof(*b));
force_assert(b);
b->ptr = NULL;
b->size = 0;
b->used = 0;
return b;
}
buffer *buffer_init_buffer(const buffer *src) {
buffer *b = buffer_init();
buffer_copy_buffer(b, src);
buffer * const b = buffer_init();
buffer_copy_string_len(b, BUF_PTR_LEN(src));
return b;
}
buffer *buffer_init_string(const char *str) {
buffer *b = buffer_init();
buffer * const b = buffer_init();
buffer_copy_string(b, str);
return b;
}
@ -102,8 +96,11 @@ __attribute_noinline__
__attribute_nonnull__
__attribute_returns_nonnull__
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);
if (b->used < 2) { /* buffer_is_blank(b) */
char * const s = buffer_string_prepare_copy(b, size);
*s = '\0'; /*(for case (1 == b->used))*/
return s;
}
/* not empty, b->used already includes a terminating 0 */
/*(note: if size larger than one lshift, use size instead of power-2)*/
@ -133,24 +130,20 @@ buffer_extend (buffer * const b, const size_t x)
* (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())*/
#if 0
char * const s = buffer_string_prepare_append(b, x);
b->used += x + (0 == b->used);
#else
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;
#endif
s[x] = '\0';
return s;
}
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)
{
size_t sz = b->used;
@ -463,11 +456,11 @@ void li_tohex_uc(char * const restrict buf, size_t buf_len, const char * const r
void buffer_substr_replace (buffer * const restrict b, const size_t offset,
const size_t len, const buffer * const restrict replace)
{
const size_t blen = buffer_string_length(b);
const size_t rlen = buffer_string_length(replace);
const size_t blen = buffer_clen(b);
const size_t rlen = buffer_clen(replace);
if (rlen > len) {
buffer_string_set_length(b, blen-len+rlen);
buffer_extend(b, blen-len+rlen);
memmove(b->ptr+offset+rlen, b->ptr+offset+len, blen-offset-len);
}
@ -475,7 +468,7 @@ void buffer_substr_replace (buffer * const restrict b, const size_t offset,
if (rlen < len) {
memmove(b->ptr+offset+rlen, b->ptr+offset+len, blen-offset-len);
buffer_string_set_length(b, blen-len+rlen);
buffer_truncate(b, blen-len+rlen);
}
}
@ -731,7 +724,7 @@ void buffer_append_string_c_escaped(buffer * const restrict b, const char * cons
*/
void buffer_urldecode_path(buffer * const b) {
const size_t len = buffer_string_length(b);
const size_t len = buffer_clen(b);
char *src = len ? memchr(b->ptr, '%', len) : NULL;
if (NULL == src) return;
@ -802,8 +795,11 @@ int buffer_is_valid_UTF8(const buffer *b) {
void buffer_path_simplify(buffer *b)
{
if (__builtin_expect( (buffer_string_is_empty(b)), 0)) {
buffer_copy_string_len(b, CONST_STR_LEN(""));
char *out = b->ptr;
char * const end = b->ptr + b->used - 1;
if (__builtin_expect( (buffer_is_blank(b)), 0)) {
buffer_blank(b);
return;
}
@ -814,8 +810,6 @@ void buffer_path_simplify(buffer *b)
}
#endif
char *out = b->ptr;
char * const end = b->ptr + b->used - 1;
*end = '/'; /*(end of path modified to avoid need to check '\0')*/
char *walk = out;
@ -874,7 +868,7 @@ void buffer_path_simplify(buffer *b)
}
*out = *end = '\0'; /* overwrite extra '/' added to end of path */
b->used = (out - b->ptr) + 1;
/*buffer_string_set_length(b, out - b->ptr);*/
/*buffer_truncate(b, out - b->ptr);*/
}
void buffer_to_lower(buffer * const b) {

170
src/buffer.h

@ -13,13 +13,11 @@ struct tm; /* declaration */
/* generic string + binary data container; contains a terminating 0 in both
* cases
*
* used == 0 indicates a special "empty" state (unset config values); ptr
* might be NULL too then. otherwise an empty string has used == 1 (and ptr[0]
* == 0);
* used == 0 indicates a special "empty" state (unset config values);
* ptr might be NULL, too.
*
* copy/append functions will ensure used >= 1 (i.e. never leave it in the
* special empty state); only buffer_copy_buffer will copy the special empty
* state.
* copy/append functions will ensure used >= 1
* (i.e. never leave it in the special empty state)
*/
typedef struct {
char *ptr;
@ -34,8 +32,9 @@ typedef struct {
__attribute_returns_nonnull__
buffer* buffer_init(void);
__attribute_nonnull__
__attribute_returns_nonnull__
buffer* buffer_init_buffer(const buffer *src); /* src can be NULL */
buffer* buffer_init_buffer(const buffer *src);
__attribute_returns_nonnull__
buffer* buffer_init_string(const char *str); /* str can be NULL */
@ -81,14 +80,6 @@ char* buffer_extend(buffer * const restrict b, size_t x);
__attribute_nonnull__
void buffer_commit(buffer *b, size_t size);
/* sets string length:
* - always stores a terminating zero to terminate the "new" string
* - does not modify the string data apart from terminating zero
* - reallocates the buffer iff needed
*/
__attribute_nonnull__
void buffer_string_set_length(buffer *b, uint32_t len);
/* clear buffer
* - invalidate buffer contents
* - unsets used chars but does not modify existing ptr contents
@ -116,13 +107,11 @@ 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 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 len);
void buffer_append_str2(buffer * restrict b, const char *s1, size_t len1, const char *s2, size_t len2);
void buffer_append_str3(buffer * restrict b, const char *s1, size_t len1, const char *s2, size_t len2, const char *s3, size_t len3);
static inline void buffer_append_string_buffer(buffer * restrict b, const buffer * restrict src);
struct const_iovec {
const void *iov_base;
@ -155,16 +144,6 @@ void li_tohex_lc(char * restrict buf, size_t buf_len, const char * restrict s, s
__attribute_nonnull__
void li_tohex_uc(char * restrict buf, size_t buf_len, const char * restrict s, size_t s_len);
/* NULL buffer or empty buffer (used == 0);
* unset "string" (buffer) config options are initialized to used == 0,
* while setting an empty string leads to used == 1
*/
__attribute_pure__
static inline int buffer_is_empty(const buffer *b);
/* NULL buffer, empty buffer (used == 0) or empty string (used == 1) */
__attribute_pure__
static inline int buffer_string_is_empty(const buffer *b);
__attribute_nonnull__
__attribute_pure__
int buffer_eq_icase_ssn(const char * const a, const char * const b, const size_t len);
@ -176,12 +155,10 @@ int buffer_eq_icase_ss(const char * const a, const size_t alen, const char * con
__attribute_nonnull__
__attribute_pure__
int buffer_eq_icase_slen(const buffer * const b, const char * const s, const size_t slen);
#define buffer_is_equal_caseless_string buffer_eq_icase_slen
__attribute_nonnull__
__attribute_pure__
int buffer_eq_slen(const buffer * const b, const char * const s, const size_t slen);
#define buffer_is_equal_string buffer_eq_slen
__attribute_nonnull__
__attribute_pure__
@ -263,16 +240,6 @@ static inline int light_isalnum(int c) {
#define light_bset(a,b) ((a) |= ((uint64_t)1uL << (b)))
__attribute_pure__
static inline uint32_t buffer_string_length(const buffer *b); /* buffer string length without terminating 0 */
__attribute_nonnull__
__attribute_pure__
static inline uint32_t buffer_string_space(const buffer *b); /* maximum length of string that can be stored without reallocating */
__attribute_nonnull__
static inline void buffer_append_slash(buffer *b); /* append '/' no non-empty strings not ending in '/' */
void buffer_append_path_len(buffer * restrict b, const char * restrict a, size_t alen); /* join strings with '/', if '/' not present */
void buffer_copy_path_len2(buffer * restrict b, const char * restrict s1, size_t len1, const char * restrict s2, size_t len2);
@ -284,17 +251,11 @@ __attribute_nonnull__
__attribute_pure__
static inline int buffer_has_pathsep_suffix (const buffer * const b);
#define BUFFER_APPEND_STRING_CONST(x, y) \
buffer_append_string_len(x, y, sizeof(y) - 1)
#define BUFFER_COPY_STRING_CONST(x, y) \
buffer_copy_string_len(x, y, sizeof(y) - 1)
#define BUFFER_INTLEN_PTR(x) (x)->used ? (int)((x)->used - 1) : 0, (x)->ptr
#define BUFFER_INTLEN_PTR(x) (int)buffer_clen(x), (x)->ptr
#define BUF_PTR_LEN(x) (x)->ptr, buffer_clen(x)
#define CONST_LEN_STR(x) (uint32_t)sizeof(x)-1, x
#define CONST_STR_LEN(x) x, (uint32_t)sizeof(x) - 1
#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x)
#define LI_NORETURN __attribute_noreturn__
@ -304,34 +265,71 @@ void log_failed_assert(const char *filename, unsigned int line, const char *msg)
#define force_assert(x) do { if (!(x)) log_failed_assert(__FILE__, __LINE__, "assertion failed: " #x); } while(0)
#define SEGFAULT() log_failed_assert(__FILE__, __LINE__, "aborted");
/* inline implementations */
static inline int buffer_is_empty(const buffer *b) {
return NULL == b || 0 == b->used;
__attribute_nonnull__
__attribute_pure__
static inline int buffer_is_unset(const buffer *b);
static inline int buffer_is_unset(const buffer *b) {
return 0 == b->used;
}
static inline int buffer_string_is_empty(const buffer *b) {
return NULL == b || b->used < 2;
__attribute_nonnull__
__attribute_pure__
static inline int buffer_is_blank(const buffer *b);
static inline int buffer_is_blank(const buffer *b) {
return b->used < 2; /* buffer_is_blank() || buffer_is_unset() */
}
static inline uint32_t buffer_string_length(const buffer *b) {
return NULL != b && 0 != b->used ? b->used - 1 : 0;
/* buffer "C" len (bytes) */
__attribute_nonnull__
__attribute_pure__
static inline uint32_t buffer_clen (const buffer *b);
static inline uint32_t buffer_clen (const buffer *b) {
return b->used - (0 != b->used);
}
/* buffer space remaining to append string without reallocating */
__attribute_nonnull__
__attribute_pure__
static inline uint32_t buffer_string_space(const buffer *b);
static inline uint32_t buffer_string_space(const buffer *b) {
return b->size ? b->size - (b->used | (0 == b->used)) : 0;
return b->size ? b->size - (b->used | (0 == b->used)) : 0;
}
__attribute_nonnull__
static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src);
static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src) {
buffer_copy_string_len(b, CONST_BUF_LEN(src));
buffer_copy_string_len(b, BUF_PTR_LEN(src));
}
static inline void buffer_append_string_buffer(buffer * restrict b, const buffer * restrict src) {
buffer_append_string_len(b, CONST_BUF_LEN(src));
__attribute_nonnull__
static inline void buffer_append_buffer(buffer * restrict b, const buffer * restrict src);
static inline void buffer_append_buffer(buffer * restrict b, const buffer * restrict src) {
buffer_append_string_len(b, BUF_PTR_LEN(src));
}
__attribute_nonnull__
static inline void buffer_truncate(buffer *b, uint32_t len);
static inline void buffer_truncate(buffer *b, uint32_t len) {
b->ptr[len] = '\0'; /* b->ptr must exist; use buffer_blank() for trunc 0 */
b->used = len + 1;
}
__attribute_nonnull__
static inline void buffer_blank(buffer *b);
static inline void buffer_blank(buffer *b) {
b->ptr ? buffer_truncate(b, 0) : (void)buffer_extend(b, 0);
}
/* append '/' to non-empty strings not ending in '/' */
__attribute_nonnull__
static inline void buffer_append_slash(buffer *b);
static inline void buffer_append_slash(buffer *b) {
uint32_t len = buffer_string_length(b);
if (len > 0 && '/' != b->ptr[len-1]) BUFFER_APPEND_STRING_CONST(b, "/");
const uint32_t len = buffer_clen(b);
if (len > 0 && '/' != b->ptr[len-1])
buffer_append_string_len(b, CONST_STR_LEN("/"));
}
static inline void buffer_clear(buffer *b) {
@ -352,4 +350,58 @@ static inline int buffer_has_pathsep_suffix (const buffer * const b) {
return (b->used > 1 && b->ptr[b->used-2] == '/');
}
/* backwards compat (deprecated; older interfaces) */
#define buffer_append_string_buffer buffer_append_buffer
#define buffer_is_equal_caseless_string buffer_eq_icase_slen
#define buffer_is_equal_string buffer_eq_slen
#define BUFFER_APPEND_STRING_CONST(x, y) \
buffer_append_string_len(x, y, sizeof(y) - 1)
#define BUFFER_COPY_STRING_CONST(x, y) \
buffer_copy_string_len(x, y, sizeof(y) - 1)
#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x)
/* NULL buffer or empty buffer (used == 0);
* unset "string" (buffer) config options are initialized to used == 0,
* while setting an empty string leads to used == 1
*/
__attribute_pure__
static inline int buffer_is_empty(const buffer *b);
static inline int buffer_is_empty(const buffer *b) {
return NULL == b || buffer_is_unset(b);
}
/* NULL buffer, empty buffer (used == 0) or empty string (used == 1) */
__attribute_pure__
static inline int buffer_string_is_empty(const buffer *b);
static inline int buffer_string_is_empty(const buffer *b) {
return NULL == b || buffer_is_blank(b);
}
/* buffer string length without terminating 0 */
__attribute_pure__
static inline uint32_t buffer_string_length(const buffer *b);
static inline uint32_t buffer_string_length(const buffer *b) {
return NULL != b ? buffer_clen(b) : 0;
}
/* sets string length:
* - deprecated; use buffer_truncate() or buffer_extend() instead
* - always stores a terminating zero to terminate the "new" string
* - does not modify the string data apart from terminating zero
* - reallocates the buffer iff needed
*/
__attribute_nonnull__
static inline void buffer_string_set_length(buffer *b, uint32_t len);
static inline void buffer_string_set_length(buffer *b, uint32_t len) {
if (len < b->size)
buffer_truncate(b, len);
else
buffer_extend(b, len - buffer_clen(b));
}
#endif

36
src/burl.c

@ -58,7 +58,7 @@ static int burl_is_unreserved (const int c)
static int burl_normalize_basic_unreserved_fix (buffer *b, buffer *t, int i, int qs)
{
int j = i;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
const unsigned char * const s = (unsigned char *)b->ptr;
unsigned char * const p =
(unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
@ -98,7 +98,7 @@ static int burl_normalize_basic_unreserved_fix (buffer *b, buffer *t, int i, int
static int burl_normalize_basic_unreserved (buffer *b, buffer *t)
{
const unsigned char * const s = (unsigned char *)b->ptr;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
unsigned int n1, n2, x;
int qs = -1;
@ -114,7 +114,7 @@ static int burl_normalize_basic_unreserved (buffer *b, buffer *t)
i+=2;
}
else if (s[i] == '#') { /* ignore fragment */
buffer_string_set_length(b, (size_t)i);
buffer_truncate(b, (size_t)i);
break;
}
else {
@ -130,7 +130,7 @@ static int burl_normalize_basic_unreserved (buffer *b, buffer *t)
static int burl_normalize_basic_required_fix (buffer *b, buffer *t, int i, int qs)
{
int j = i;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
const unsigned char * const s = (unsigned char *)b->ptr;
unsigned char * const p =
(unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
@ -173,7 +173,7 @@ static int burl_normalize_basic_required_fix (buffer *b, buffer *t, int i, int q
static int burl_normalize_basic_required (buffer *b, buffer *t)
{
const unsigned char * const s = (unsigned char *)b->ptr;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
unsigned int n1, n2, x;
int qs = -1;
@ -192,7 +192,7 @@ static int burl_normalize_basic_required (buffer *b, buffer *t)
i+=2;
}
else if (s[i] == '#') { /* ignore fragment */
buffer_string_set_length(b, (size_t)i);
buffer_truncate(b, (size_t)i);
break;
}
else {
@ -208,7 +208,7 @@ static int burl_normalize_basic_required (buffer *b, buffer *t)
static int burl_contains_ctrls (const buffer *b)
{
const char * const s = b->ptr;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
for (int i = 0; i < used; ++i) {
if (s[i] == '%' && (s[i+1] < '2' || (s[i+1] == '7' && s[i+2] == 'F')))
return 1;
@ -220,7 +220,7 @@ static int burl_contains_ctrls (const buffer *b)
static void burl_normalize_qs20_to_plus_fix (buffer *b, int i)
{
char * const s = b->ptr;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
int j = i;
for (; i < used; ++i, ++j) {
s[j] = s[i];
@ -229,14 +229,14 @@ static void burl_normalize_qs20_to_plus_fix (buffer *b, int i)
i+=2;
}
}
buffer_string_set_length(b, j);
buffer_truncate(b, j);
}
static void burl_normalize_qs20_to_plus (buffer *b, int qs)
{
const char * const s = b->ptr;
const int used = qs < 0 ? 0 : (int)buffer_string_length(b);
const int used = qs < 0 ? 0 : (int)buffer_clen(b);
int i;
if (qs < 0) return;
for (i = qs+1; i < used; ++i) {
@ -249,7 +249,7 @@ static void burl_normalize_qs20_to_plus (buffer *b, int qs)
static int burl_normalize_2F_to_slash_fix (buffer *b, int qs, int i)
{
char * const s = b->ptr;
const int blen = (int)buffer_string_length(b);
const int blen = (int)buffer_clen(b);
const int used = qs < 0 ? blen : qs;
int j = i;
for (; i < used; ++i, ++j) {
@ -265,7 +265,7 @@ static int burl_normalize_2F_to_slash_fix (buffer *b, int qs, int i)
qs = j;
j += qslen;
}
buffer_string_set_length(b, j);
buffer_truncate(b, j);
return qs;
}
@ -274,7 +274,7 @@ static int burl_normalize_2F_to_slash (buffer *b, int qs, int flags)
{
/*("%2F" must already have been uppercased during normalization)*/
const char * const s = b->ptr;
const int used = qs < 0 ? (int)buffer_string_length(b) : qs;
const int used = qs < 0 ? (int)buffer_clen(b) : qs;
for (int i = 0; i < used; ++i) {
if (s[i] == '%' && s[i+1] == '2' && s[i+2] == 'F') {
return (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE)
@ -289,7 +289,7 @@ static int burl_normalize_2F_to_slash (buffer *b, int qs, int flags)
static int burl_normalize_path (buffer *b, buffer *t, int qs, int flags)
{
const unsigned char * const s = (unsigned char *)b->ptr;
const int used = (int)buffer_string_length(b);
const int used = (int)buffer_clen(b);
int path_simplify = 0;
for (int i = 0, len = qs < 0 ? used : qs; i < len; ++i) {
if (s[i] == '.' && (s[i+1] != '.' || ++i)
@ -308,14 +308,14 @@ static int burl_normalize_path (buffer *b, buffer *t, int qs, int flags)
if (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT) return -2;
if (qs >= 0) {
buffer_copy_string_len(t, b->ptr+qs, used - qs);
buffer_string_set_length(b, qs);
buffer_truncate(b, qs);
}
buffer_path_simplify(b);
if (qs >= 0) {
qs = (int)buffer_string_length(b);
buffer_append_string_len(b, CONST_BUF_LEN(t));
qs = (int)buffer_clen(b);
buffer_append_string_len(b, BUF_PTR_LEN(t));
}
}
@ -490,7 +490,7 @@ void burl_append (buffer * const b, const char * const str, const size_t len, co
return;
}
if (flags & (BURL_TOUPPER|BURL_TOLOWER)) off = buffer_string_length(b);
if (flags & (BURL_TOUPPER|BURL_TOLOWER)) off = buffer_clen(b);
if (flags & BURL_ENCODE_NONE) {
buffer_append_string_len(b, str, len);

67
src/chunk.c

@ -46,20 +46,6 @@ void chunkqueue_set_tempdirs_default_reset (void)
chunkqueue_default_tempfile_size = DEFAULT_TEMPFILE_SIZE;
}
/* chunk buffer (c->mem) is never NULL; specialize routines from buffer.h */
__attribute_pure__
static inline size_t chunk_buffer_string_length(const buffer *b) {
return 0 != b->used ? b->used - 1 : 0;
}
__attribute_pure__
static inline int chunk_buffer_string_is_empty(const buffer *b) {
return b->used < 2;
}
__attribute_pure__
static inline size_t chunk_buffer_string_space(const buffer *b) {
return b->size ? b->size - (b->used | (0 == b->used)) : 0;
}
chunkqueue *chunkqueue_init(chunkqueue *cq) {
/* (if caller passes non-NULL cq, it must be 0-init) */
if (NULL == cq) {
@ -101,7 +87,7 @@ static chunk *chunk_init(size_t sz) {
static void chunk_reset_file_chunk(chunk *c) {
if (c->file.is_temp) {
c->file.is_temp = 0;
if (!chunk_buffer_string_is_empty(c->mem))
if (!buffer_is_blank(c->mem))
unlink(c->mem->ptr);
}
if (c->file.refchg) {
@ -213,7 +199,7 @@ void chunk_buffer_release(buffer *b) {
}
size_t chunk_buffer_prepare_append(buffer * const b, size_t sz) {
if (sz > chunk_buffer_string_space(b)) {
if (sz > buffer_string_space(b)) {
sz += b->used ? b->used : 1;
buffer * const cb = chunk_buffer_acquire_sz(sz);
/* swap buffer contents and copy original b->ptr into larger b->ptr */
@ -225,7 +211,7 @@ size_t chunk_buffer_prepare_append(buffer * const b, size_t sz) {
memcpy(b->ptr, tb.ptr, tb.used);
chunk_buffer_release(cb);
}
return chunk_buffer_string_space(b);
return buffer_string_space(b);
}
__attribute_returns_nonnull__
@ -294,7 +280,7 @@ __attribute_pure__
static off_t chunk_remaining_length(const chunk *c) {
/* MEM_CHUNK or FILE_CHUNK */
return (c->type == MEM_CHUNK
? (off_t)chunk_buffer_string_length(c->mem)
? (off_t)buffer_clen(c->mem)
: c->file.length)
- c->offset;
}
@ -340,13 +326,13 @@ static chunk * chunkqueue_append_mem_chunk(chunkqueue *cq, size_t sz) {
__attribute_returns_nonnull__
static chunk * chunkqueue_append_file_chunk(chunkqueue * const restrict cq, const buffer * const restrict fn, off_t offset, off_t len) {
chunk *c = chunk_acquire(buffer_string_length(fn)+1);
chunk *c = chunk_acquire((fn ? buffer_clen(fn) : 0)+1);
chunkqueue_append_chunk(cq, c);
c->type = FILE_CHUNK;
c->offset = offset;
c->file.length = offset + len;
cq->bytes_in += len;
buffer_copy_buffer(c->mem, fn);
if (fn) buffer_copy_buffer(c->mem, fn);
return c;
}
@ -377,7 +363,7 @@ static int chunkqueue_append_mem_extend_chunk(chunkqueue * const restrict cq, co
chunk *c = cq->last;
if (0 == len) return 1;
if (c != NULL && c->type == MEM_CHUNK
&& chunk_buffer_string_space(c->mem) >= len) {
&& buffer_string_space(c->mem) >= len) {
buffer_append_string_len(c->mem, mem, len);
cq->bytes_in += len;
return 1;
@ -388,7 +374,7 @@ static int chunkqueue_append_mem_extend_chunk(chunkqueue * const restrict cq, co
void chunkqueue_append_buffer(chunkqueue * const restrict cq, buffer * const restrict mem) {
chunk *c;
size_t len = buffer_string_length(mem);
size_t len = mem ? buffer_clen(mem) : 0;
if (len < 256 && chunkqueue_append_mem_extend_chunk(cq, mem->ptr, len)) return;
c = chunkqueue_append_mem_chunk(cq, chunk_buf_sz);
@ -449,7 +435,7 @@ buffer * chunkqueue_prepend_buffer_open(chunkqueue *cq) {
void chunkqueue_prepend_buffer_commit(chunkqueue *cq) {
cq->bytes_in += chunk_buffer_string_length(cq->first->mem);
cq->bytes_in += buffer_clen(cq->first->mem);
}
@ -465,7 +451,7 @@ buffer * chunkqueue_append_buffer_open(chunkqueue *cq) {
void chunkqueue_append_buffer_commit(chunkqueue *cq) {
cq->bytes_in += chunk_buffer_string_length(cq->last->mem);
cq->bytes_in += buffer_clen(cq->last->mem);
}
@ -478,17 +464,17 @@ char * chunkqueue_get_memory(chunkqueue * const restrict cq, size_t * const rest
chunk *c = cq->last;
if (NULL != c && MEM_CHUNK == c->type) {
/* return pointer into existing buffer if large enough */
size_t avail = chunk_buffer_string_space(c->mem);
size_t avail = buffer_string_space(c->mem);
if (avail >= sz) {
*len = avail;
b = c->mem;
return b->ptr + chunk_buffer_string_length(b);
return b->ptr + buffer_clen(b);
}
}
/* allocate new chunk */
b = chunkqueue_append_buffer_open_sz(cq, sz);
*len = chunk_buffer_string_space(b);
*len = buffer_string_space(b);
return b->ptr;
}
@ -499,11 +485,11 @@ void chunkqueue_use_memory(chunkqueue * const restrict cq, chunk *ckpt, size_t l
buffer_commit(b, len);
cq->bytes_in += len;
if (cq->last == ckpt || NULL == ckpt || MEM_CHUNK != ckpt->type
|| len > chunk_buffer_string_space(ckpt->mem)) return;
|| len > buffer_string_space(ckpt->mem)) return;
buffer_append_string_buffer(ckpt->mem, b);
}
else if (!chunk_buffer_string_is_empty(b)) { /*(cq->last == ckpt)*/
else if (!buffer_is_blank(b)) { /*(cq->last == ckpt)*/
return; /* last chunk is not empty */
}
@ -616,7 +602,7 @@ static chunk *chunkqueue_get_append_tempfile(chunkqueue * const restrict cq, log
for (errno = EIO; cq->tempdir_idx < cq->tempdirs->used; ++cq->tempdir_idx) {
data_string *ds = (data_string *)cq->tempdirs->data[cq->tempdir_idx];
buffer_copy_path_len2(template,
CONST_BUF_LEN(&ds->value),
BUF_PTR_LEN(&ds->value),
CONST_STR_LEN("lighttpd-upload-XXXXXX"));
if (-1 != (fd = fdevent_mkstemp_append(template->ptr))) break;
}
@ -877,10 +863,10 @@ void chunkqueue_compact_mem_offset(chunkqueue * const cq) {
if (c->type != MEM_CHUNK) return; /*(should not happen)*/
buffer * const restrict b = c->mem;
size_t len = chunk_buffer_string_length(b) - c->offset;
size_t len = buffer_clen(b) - c->offset;
memmove(b->ptr, b->ptr+c->offset, len);
c->offset = 0;
buffer_string_set_length(b, len);
buffer_truncate(b, len);
}
void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
@ -888,10 +874,10 @@ void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
* which is currently always true when reading input from client */
chunk *c = cq->first;
buffer *b = c->mem;
size_t len = chunk_buffer_string_length(b) - c->offset;
size_t len = buffer_clen(b) - c->offset;
if (len >= clen) return;
if (b->size > clen) {
if (chunk_buffer_string_space(b) < clen - len)
if (buffer_string_space(b) < clen - len)
chunkqueue_compact_mem_offset(cq);
}
else {
@ -904,7 +890,7 @@ void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
}
for (chunk *fc = c; ((clen -= len) && (c = fc->next)); ) {
len = chunk_buffer_string_length(c->mem) - c->offset;
len = buffer_clen(c->mem) - c->offset;
if (len > clen) {
buffer_append_string_len(b, c->mem->ptr + c->offset, clen);
c->offset += clen;
@ -1076,7 +1062,7 @@ static ssize_t
chunkqueue_write_chunk_mem (const int fd, const chunk * const restrict c)
{
const void * const buf = c->mem->ptr + c->offset;
const size_t count = chunk_buffer_string_length(c->mem) - (size_t)c->offset;
const size_t count = buffer_clen(c->mem) - (size_t)c->offset;
ssize_t wr;
do { wr = write(fd, buf, count); } while (-1 == wr && errno == EINTR);
return wr;
@ -1144,14 +1130,14 @@ chunkqueue_small_resp_optim (chunkqueue * const restrict cq)
buffer *b = c->mem;
off_t len = filec->file.length - filec->offset;
if ((size_t)len > chunk_buffer_string_space(b)) {
if ((size_t)len > buffer_string_space(b)) {
chunk * const nc = chunk_acquire((size_t)len+1);
c->next = nc;
nc->next = filec;
b = nc->mem;
}
char * const ptr = b->ptr + chunk_buffer_string_length(b);
char * const ptr = b->ptr + buffer_clen(b);
ssize_t rd;
offset = 0; /*(reuse offset var for offset into mem buffer)*/
do {
@ -1180,8 +1166,7 @@ chunkqueue_peek_data (chunkqueue * const cq,
switch (c->type) {
case MEM_CHUNK:
{
uint32_t have =
chunk_buffer_string_length(c->mem) - (uint32_t)c->offset;
uint32_t have = buffer_clen(c->mem) - (uint32_t)c->offset;
if (have > space)
have = space;
if (*dlen)
@ -1277,7 +1262,7 @@ chunkqueue_read_squash (chunkqueue * const restrict cq, log_error_st * const res
chunk_release(c);
return NULL;
}
buffer_string_set_length(c->mem, dlen);
buffer_truncate(c->mem, dlen);
chunkqueue_release_chunks(cq);
chunkqueue_append_chunk(cq, c);

6
src/configfile-glue.c

@ -516,7 +516,7 @@ static cond_result_t config_check_cond_nocache(request_st * const r, const data_
l = &r->uri.authority;
if (buffer_string_is_empty(l)) {
if (buffer_is_blank(l)) {
l = (buffer *)&empty_string;
break;
}
@ -592,7 +592,7 @@ static cond_result_t config_check_cond_nocache(request_st * const r, const data_
case COMP_HTTP_REQUEST_HEADER:
*((const buffer **)&l) =
http_header_request_get(r, dc->ext, CONST_BUF_LEN(&dc->comp_tag));
http_header_request_get(r, dc->ext, BUF_PTR_LEN(&dc->comp_tag));
if (NULL == l) l = (buffer *)&empty_string;
break;
case COMP_HTTP_REQUEST_METHOD:
@ -720,7 +720,7 @@ static int data_config_pcre_exec(const data_config *dc, cond_cache_t *cache, con
#define elementsof(x) (sizeof(x) / sizeof(x[0]))
#endif
cache->patterncount =
pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(b), 0, 0,
pcre_exec(dc->regex, dc->regex_study, BUF_PTR_LEN(b), 0, 0,
cond_match->matches, elementsof(cond_match->matches));
if (cache->patterncount > 0)
cond_match->comp_value = b; /*holds pointer to b (!) for pattern subst*/

104
src/configfile.c

@ -215,7 +215,6 @@ void config_patch_config(request_st * const r) {
void config_reset_config(request_st * const r) {
/* initialize request_config (r->conf) from top-level request_config */
config_data_base * const p = r->con->config_data_base;
r->server_name = p->defaults.server_name;
memcpy(&r->conf, &p->defaults, sizeof(request_config));
}
@ -304,7 +303,7 @@ static void config_check_module_duplicates (server *srv) {
if (buffer_is_equal(m, n)) break; /* duplicate */
}
if (j == modules->used)
array_insert_value(modules, CONST_BUF_LEN(m));
array_insert_value(modules, BUF_PTR_LEN(m));
}
array_free(srv->srvconf.modules);
srv->srvconf.modules = modules;
@ -330,7 +329,7 @@ static void config_compat_module_prepend (server *srv, const char *module, uint3
for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
data_string *ds = (data_string *)srv->srvconf.modules->data[i];
array_insert_value(modules, CONST_BUF_LEN(&ds->value));
array_insert_value(modules, BUF_PTR_LEN(&ds->value));
}
array_free(srv->srvconf.modules);
@ -341,7 +340,7 @@ static void config_warn_authn_module (server *srv, const char *module, uint32_t
buffer * const tb = srv->tmp_buf;
buffer_copy_string_len(tb, CONST_STR_LEN("mod_authn_"));
buffer_append_string_len(tb, module, len);
array_insert_value(srv->srvconf.modules, CONST_BUF_LEN(tb));
array_insert_value(srv->srvconf.modules, BUF_PTR_LEN(tb));
log_error(srv->errh, __FILE__, __LINE__,
"Warning: please add \"mod_authn_%s\" to server.modules list "
"in lighttpd.conf. A future release of lighttpd 1.4.x will "
@ -503,7 +502,7 @@ static void config_deprecate_module_compress (server *srv) {
buffer *m = &((data_string *)srv->srvconf.modules->data[i])->value;
if (buffer_eq_slen(m, CONST_STR_LEN("mod_compress")))
continue;
array_insert_value(a, CONST_BUF_LEN(m));
array_insert_value(a, BUF_PTR_LEN(m));
}
array_free(srv->srvconf.modules);
srv->srvconf.modules = a;
@ -755,19 +754,24 @@ static int config_insert_srvconf(server *srv) {
srv->srvconf.port = cpv->v.shrt;
break;
case 4: /* server.bind */
srv->srvconf.bindhost = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
srv->srvconf.bindhost = cpv->v.b;
break;
case 5: /* server.network-backend */
srv->srvconf.network_backend = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
srv->srvconf.network_backend = cpv->v.b;
break;
case 6: /* server.chroot */
srv->srvconf.changeroot = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
srv->srvconf.changeroot = cpv->v.b;
break;
case 7: /* server.username */
srv->srvconf.username = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
srv->srvconf.username = cpv->v.b;
break;
case 8: /* server.groupname */
srv->srvconf.groupname = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
srv->srvconf.groupname = cpv->v.b;
break;
case 9: /* server.errorlog */ /* moved to config_insert() */
/*srv->srvconf.errorlog_file = cpv->v.b;*/
@ -779,7 +783,8 @@ static int config_insert_srvconf(server *srv) {
srv->srvconf.errorlog_use_syslog = (unsigned short)cpv->v.u;
break;
case 12:/* server.syslog-facility */
srv->srvconf.syslog_facility = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
srv->srvconf.syslog_facility = cpv->v.b;
break;
case 13:/* server.core-files */
srv->srvconf.enable_cores = (unsigned short)cpv->v.u;
@ -788,7 +793,8 @@ static int config_insert_srvconf(server *srv) {
srv->srvconf.event_handler = cpv->v.b->ptr;
break;
case 15:/* server.pid-file */
*(const buffer **)&srv->srvconf.pid_file = cpv->v.b;
if (!buffer_is_blank(cpv->v.b))
*(const buffer **)&srv->srvconf.pid_file = cpv->v.b;
break;
case 16:/* server.max-worker */
srv->srvconf.max_worker = (unsigned short)cpv->v.u;
@ -1018,10 +1024,13 @@ static int config_insert(server *srv) {
for (; -1 != cpv->k_id; ++cpv) {
switch (cpv->k_id) {
case 0: /* server.document-root */