Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libhtp for openSUSE:Factory checked in at 2022-06-28 15:22:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libhtp (Old) and /work/SRC/openSUSE:Factory/.libhtp.new.1548 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libhtp" Tue Jun 28 15:22:57 2022 rev:11 rq:985534 version:0.5.40 Changes: -------- --- /work/SRC/openSUSE:Factory/libhtp/libhtp.changes 2021-11-22 23:04:50.245800489 +0100 +++ /work/SRC/openSUSE:Factory/.libhtp.new.1548/libhtp.changes 2022-06-28 15:23:16.774023646 +0200 @@ -1,0 +2,13 @@ +Mon Jun 27 21:32:51 UTC 2022 - Otto Hollmann <[email protected]> + +- Update to version 0.5.40 + * uri: optionally allows spaces in uri + * ints: integer handling improvements + * headers: continue on nul byte + * headers: consistent trailing space handling + * list: fix integer overflow + * util: remove unused htp_utf8_decode + * fix 100-continue with CL 0 + * lzma: don't do unnecessary realloc + +------------------------------------------------------------------- Old: ---- libhtp-0.5.39.tar.gz New: ---- libhtp-0.5.40.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libhtp.spec ++++++ --- /var/tmp/diff_new_pack.I3tbyf/_old 2022-06-28 15:23:17.154024212 +0200 +++ /var/tmp/diff_new_pack.I3tbyf/_new 2022-06-28 15:23:17.158024219 +0200 @@ -1,7 +1,7 @@ # # spec file for package libhtp # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define sover 2 %define lname %{name}%{sover} Name: libhtp -Version: 0.5.39 +Version: 0.5.40 Release: 0 Summary: HTTP normalizer and parser License: BSD-3-Clause ++++++ libhtp-0.5.39.tar.gz -> libhtp-0.5.40.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/ChangeLog new/libhtp-0.5.40/ChangeLog --- old/libhtp-0.5.39/ChangeLog 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/ChangeLog 2022-04-21 07:58:30.000000000 +0200 @@ -1,5 +1,24 @@ -0.5.39 (16 Nov 2021) --------------------- +0.5.40 (21 April 2022) +---------------------- + +- uri: optionally allows spaces in uri + +- ints: integer handling improvements + +- headers: continue on nul byte + +- headers: consistent trailing space handling + +- list: fix integer overflow + +- util: remove unused htp_utf8_decode + +- fix 100-continue with CL 0 + +- lzma: don't do unnecessary realloc + +0.5.39 (16 November 2021) +------------------------- - host: ipv6 address is a valid host @@ -7,8 +26,8 @@ - test and fuzz improvements -0.5.38 (30 Jun 2021) --------------------- +0.5.38 (30 June 2021) +--------------------- - consume empty lines when parsing chunks to avoid quadratic complexity diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/VERSION new/libhtp-0.5.40/VERSION --- old/libhtp-0.5.39/VERSION 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/VERSION 2022-04-21 07:58:30.000000000 +0200 @@ -1,2 +1,2 @@ # This file is intended to be sourced by sh -PKG_VERSION=0.5.39 +PKG_VERSION=0.5.40 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_config.c new/libhtp-0.5.40/htp/htp_config.c --- old/libhtp-0.5.39/htp/htp_config.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_config.c 2022-04-21 07:58:30.000000000 +0200 @@ -163,6 +163,7 @@ cfg->response_lzma_layer_limit = 1; // default is only one layer cfg->compression_bomb_limit = HTP_COMPRESSION_BOMB_LIMIT; cfg->compression_time_limit = HTP_COMPRESSION_TIME_LIMIT_USEC; + cfg->allow_space_uri = 0; // Default settings for URL-encoded data. @@ -566,6 +567,11 @@ cfg->request_decompression_enabled = enabled; } +void htp_config_set_allow_space_uri(htp_cfg_t *cfg, int allow_space_uri) { + if (cfg == NULL) return; + cfg->allow_space_uri = allow_space_uri; +} + int htp_config_set_server_personality(htp_cfg_t *cfg, enum htp_server_personality_t personality) { if (cfg == NULL) return HTP_ERROR; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_config.h new/libhtp-0.5.40/htp/htp_config.h --- old/libhtp-0.5.39/htp/htp_config.h 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_config.h 2022-04-21 07:58:30.000000000 +0200 @@ -523,6 +523,14 @@ void htp_config_set_parse_request_cookies(htp_cfg_t *cfg, int parse_request_cookies); /** + * Enable or disable spaces in URIs. Disabled by default. + * + * @param[in] cfg + * @param[in] allow_space_uri + */ +void htp_config_set_allow_space_uri(htp_cfg_t *cfg, int allow_space_uri); + +/** * Configures whether consecutive path segment separators will be compressed. When enabled, a path * such as "/one//two" will be normalized to "/one/two". Backslash conversion and path segment separator * decoding are carried out before compression. For example, the path "/one\\/two\/%5cthree/%2f//four" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_config_private.h new/libhtp-0.5.40/htp/htp_config_private.h --- old/libhtp-0.5.39/htp/htp_config_private.h 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_config_private.h 2022-04-21 07:58:30.000000000 +0200 @@ -193,6 +193,9 @@ /** How many extracted files are allowed in a single Multipart request? */ int extract_request_files_limit; + /** Whether to allow spaces in URI. */ + int allow_space_uri; + /** The location on disk where temporary files will be created. */ char *tmpdir; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_list.c new/libhtp-0.5.40/htp/htp_list.c --- old/libhtp-0.5.39/htp/htp_list.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_list.c 2022-04-21 07:58:30.000000000 +0200 @@ -98,7 +98,7 @@ void *htp_list_array_get(const htp_list_array_t *l, size_t idx) { if (l == NULL) return NULL; - if (idx + 1 > l->current_size) return NULL; + if (idx >= l->current_size) return NULL; if (l->first + idx < l->max_size) { return (void *) l->elements[l->first + idx]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_request_generic.c new/libhtp-0.5.40/htp/htp_request_generic.c --- old/libhtp-0.5.39/htp/htp_request_generic.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_request_generic.c 2022-04-21 07:58:30.000000000 +0200 @@ -227,8 +227,7 @@ } // Look for the end of field-content. - value_end = value_start; - while ((value_end < len) && (data[value_end] != '\0')) value_end++; + value_end = len; // Ignore LWS after field-content. prev = value_end - 1; @@ -364,29 +363,55 @@ start = pos; bad_delim = 0; - - // The URI ends with the first whitespace. - while ((pos < len) && (data[pos] != 0x20)) { - if (!bad_delim && htp_is_space(data[pos])) { - bad_delim++; + if (tx->connp->cfg->allow_space_uri) { + pos = len - 1; + // Skips the spaces at the end of line (after protocol) + while (pos > start && htp_is_space(data[pos])) pos--; + // The URI ends with the last whitespace. + while ((pos > start) && (data[pos] != 0x20)) { + if (!bad_delim && htp_is_space(data[pos])) { + bad_delim++; + } + pos--; } - pos++; - } - /* if we've seen some 'bad' delimiters, we retry with those */ - if (bad_delim && pos == len) { - // special case: even though RFC's allow only SP (0x20), many - // implementations allow other delimiters, like tab or other - // characters that isspace() accepts. - pos = start; - while ((pos < len) && (!htp_is_space(data[pos]))) pos++; - } -// Too much performance overhead for fuzzing + /* if we've seen some 'bad' delimiters, we retry with those */ + if (bad_delim && pos == start) { + // special case: even though RFC's allow only SP (0x20), many + // implementations allow other delimiters, like tab or other + // characters that isspace() accepts. + while ((pos < len) && (!htp_is_space(data[pos]))) pos++; + } + if (bad_delim) { #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (bad_delim) { - // warn regardless if we've seen non-compliant chars - htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: URI contains non-compliant delimiter"); - } + // warn regardless if we've seen non-compliant chars + htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: URI contains non-compliant delimiter"); #endif + } else if (pos == start) { + pos = len; + } + } else { + // The URI ends with the first whitespace. + while ((pos < len) && (data[pos] != 0x20)) { + if (!bad_delim && htp_is_space(data[pos])) { + bad_delim++; + } + pos++; + } + /* if we've seen some 'bad' delimiters, we retry with those */ + if (bad_delim && pos == len) { + // special case: even though RFC's allow only SP (0x20), many + // implementations allow other delimiters, like tab or other + // characters that isspace() accepts. + pos = start; + while ((pos < len) && (!htp_is_space(data[pos]))) pos++; + } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (bad_delim) { + // warn regardless if we've seen non-compliant chars + htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: URI contains non-compliant delimiter"); + } +#endif + } tx->request_uri = bstr_dup_mem(data + start, pos - start); if (tx->request_uri == NULL) return HTP_ERROR; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_response.c new/libhtp-0.5.40/htp/htp_response.c --- old/libhtp-0.5.39/htp/htp_response.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_response.c 2022-04-21 07:58:30.000000000 +0200 @@ -603,29 +603,37 @@ } // Check for an interim "100 Continue" response. Ignore it if found, and revert back to RES_LINE. - if (connp->out_tx->response_status_number == 100 && te == NULL && cl == NULL) { - if (connp->out_tx->seen_100continue != 0) { - htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Already seen 100-Continue."); - return HTP_ERROR; + if (connp->out_tx->response_status_number == 100 && te == NULL) { + int is100continue = 1; + if (cl != NULL){ + if (htp_parse_content_length(cl->value, connp) > 0) { + is100continue = 0; + } } + if (is100continue) { + if (connp->out_tx->seen_100continue != 0) { + htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Already seen 100-Continue."); + return HTP_ERROR; + } + + // Ignore any response headers seen so far. + htp_header_t *h = NULL; + for (size_t i = 0, n = htp_table_size(connp->out_tx->response_headers); i < n; i++) { + h = htp_table_get_index(connp->out_tx->response_headers, i, NULL); + bstr_free(h->name); + bstr_free(h->value); + free(h); + } + + htp_table_clear(connp->out_tx->response_headers); + + // Expecting to see another response line next. + connp->out_state = htp_connp_RES_LINE; + connp->out_tx->response_progress = HTP_RESPONSE_LINE; + connp->out_tx->seen_100continue++; - // Ignore any response headers seen so far. - htp_header_t *h = NULL; - for (size_t i = 0, n = htp_table_size(connp->out_tx->response_headers); i < n; i++) { - h = htp_table_get_index(connp->out_tx->response_headers, i, NULL); - bstr_free(h->name); - bstr_free(h->value); - free(h); + return HTP_OK; } - - htp_table_clear(connp->out_tx->response_headers); - - // Expecting to see another response line next. - connp->out_state = htp_connp_RES_LINE; - connp->out_tx->response_progress = HTP_RESPONSE_LINE; - connp->out_tx->seen_100continue++; - - return HTP_OK; } // A request can indicate it waits for headers validation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_response_generic.c new/libhtp-0.5.40/htp/htp_response_generic.c --- old/libhtp-0.5.39/htp/htp_response_generic.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_response_generic.c 2022-04-21 07:58:30.000000000 +0200 @@ -221,6 +221,12 @@ break; } } + // Ignore LWS after field-content. + prev = value_end - 1; + while ((prev > value_start) && (htp_is_lws(data[prev]))) { + prev--; + value_end--; + } // Now extract the name and the value. h->name = bstr_dup_mem(data + name_start, name_end - name_start); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_utf8_decoder.c new/libhtp-0.5.40/htp/htp_utf8_decoder.c --- old/libhtp-0.5.39/htp/htp_utf8_decoder.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_utf8_decoder.c 2022-04-21 07:58:30.000000000 +0200 @@ -97,26 +97,6 @@ }; /** - * Process one byte of UTF-8 data and return a code point if one is available. - * - * @param[in] state - * @param[in] codep - * @param[in] byte - * @return HTP_UTF8_ACCEPT for a valid character, HTP_UTF8_REJECT for an invalid character, - * or something else if the character has not yet been formed - */ -uint32_t htp_utf8_decode(uint32_t* state, uint32_t* codep, uint32_t byte) { - uint32_t type = utf8d[byte]; - - *codep = (*state != HTP_UTF8_ACCEPT) ? - (byte & 0x3fu) | (*codep << 6) : - (0xff >> type) & (byte); - - *state = utf8d[256 + *state*16 + type]; - return *state; -} - -/** * Process one byte of UTF-8 data and return a code point if one is available. Allows * overlong characters in input. * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_utf8_decoder.h new/libhtp-0.5.40/htp/htp_utf8_decoder.h --- old/libhtp-0.5.39/htp/htp_utf8_decoder.h 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_utf8_decoder.h 2022-04-21 07:58:30.000000000 +0200 @@ -76,7 +76,6 @@ #define HTP_UTF8_ACCEPT 0 #define HTP_UTF8_REJECT 1 -uint32_t htp_utf8_decode(uint32_t* state, uint32_t* codep, uint32_t byte); uint32_t htp_utf8_decode_allow_overlong(uint32_t* state, uint32_t* codep, uint32_t byte); #ifdef __cplusplus diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/htp_util.c new/libhtp-0.5.40/htp/htp_util.c --- old/libhtp-0.5.39/htp/htp_util.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/htp_util.c 2022-04-21 07:58:30.000000000 +0200 @@ -1147,10 +1147,10 @@ * @param[in] data * @return decoded byte */ -static int decode_u_encoding_path(htp_cfg_t *cfg, htp_tx_t *tx, unsigned char *data) { - unsigned int c1 = x2c(data); - unsigned int c2 = x2c(data + 2); - int r = cfg->decoder_cfgs[HTP_DECODER_URL_PATH].bestfit_replacement_byte; +static uint8_t decode_u_encoding_path(htp_cfg_t *cfg, htp_tx_t *tx, unsigned char *data) { + uint8_t c1 = x2c(data); + uint8_t c2 = x2c(data + 2); + uint8_t r = cfg->decoder_cfgs[HTP_DECODER_URL_PATH].bestfit_replacement_byte; if (c1 == 0x00) { r = c2; @@ -1203,9 +1203,9 @@ * @param[in] data * @return decoded byte */ -static int decode_u_encoding_params(htp_cfg_t *cfg, enum htp_decoder_ctx_t ctx, unsigned char *data, uint64_t *flags) { - unsigned int c1 = x2c(data); - unsigned int c2 = x2c(data + 2); +static uint8_t decode_u_encoding_params(htp_cfg_t *cfg, enum htp_decoder_ctx_t ctx, unsigned char *data, uint64_t *flags) { + uint8_t c1 = x2c(data); + uint8_t c2 = x2c(data + 2); // Check for overlong usage first. if (c1 == 0) { @@ -1222,7 +1222,7 @@ // Use best-fit mapping. unsigned char *p = cfg->decoder_cfgs[ctx].bestfit_map; - int r = cfg->decoder_cfgs[ctx].bestfit_replacement_byte; + uint8_t r = cfg->decoder_cfgs[ctx].bestfit_replacement_byte; // TODO Optimize lookup. @@ -1267,7 +1267,7 @@ int previous_was_separator = 0; while ((rpos < len) && (wpos < len)) { - int c = data[rpos]; + uint8_t c = data[rpos]; // Decode encoded characters if (c == '%') { @@ -1489,7 +1489,7 @@ // Lowercase characters, if necessary if (cfg->decoder_cfgs[HTP_DECODER_URL_PATH].convert_lowercase) { - c = tolower(c); + c = (uint8_t) tolower(c); } // If we're compressing separators then we need @@ -1557,7 +1557,7 @@ size_t wpos = 0; while ((rpos < len) && (wpos < len)) { - int c = data[rpos]; + uint8_t c = data[rpos]; // Decode encoded characters. if (c == '%') { @@ -1957,7 +1957,7 @@ // the output buffer, including the initial "/" character (if // any) and any subsequent characters up to, but not including, // the next "/" character or the end of the input buffer. - data[wpos++] = c; + data[wpos++] = (uint8_t) c; while ((rpos < len) && (data[rpos] != '/') && (wpos < len)) { data[wpos++] = data[rpos++]; @@ -2042,7 +2042,7 @@ i = 0; char *p = buf + strlen(buf); while ((offset + i < len) && (i < 16)) { - int c = data[offset + i]; + uint8_t c = data[offset + i]; if (isprint(c)) { *p++ = c; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/htp/lzma/LzmaDec.c new/libhtp-0.5.40/htp/lzma/LzmaDec.c --- old/libhtp-0.5.39/htp/lzma/LzmaDec.c 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/htp/lzma/LzmaDec.c 2022-04-21 07:58:30.000000000 +0200 @@ -634,15 +634,15 @@ if (limit - p->dicPos > rem) { if (p->dicBufSize < p->prop.dicSize) { p->dicBufSize = p->prop.dicSize; + if (p->dicBufSize > memlimit) { + return SZ_ERROR_MEM; + } + Byte *tmp = realloc(p->dic, p->dicBufSize); + if (!tmp) { + return SZ_ERROR_MEM; + } + p->dic = tmp; } - if (p->dicBufSize > memlimit) { - return SZ_ERROR_MEM; - } - Byte *tmp = realloc(p->dic, p->dicBufSize); - if (!tmp) { - return SZ_ERROR_MEM; - } - p->dic = tmp; limit2 = p->dicPos + rem; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/test/files/99-expect-100.t new/libhtp-0.5.40/test/files/99-expect-100.t --- old/libhtp-0.5.39/test/files/99-expect-100.t 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/test/files/99-expect-100.t 2022-04-21 07:58:30.000000000 +0200 @@ -17,6 +17,7 @@ <<< HTTP/1.0 100 continue +Content-Length: 0 >>> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/test/test_main.cpp new/libhtp-0.5.40/test/test_main.cpp --- old/libhtp-0.5.39/test/test_main.cpp 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/test/test_main.cpp 2022-04-21 07:58:30.000000000 +0200 @@ -154,7 +154,7 @@ break; case 8: ASSERT_EQ(0, bstr_cmp_c(h->name, "Header-With-NUL")); - ASSERT_EQ(0, bstr_cmp_c(h->value, "BEFORE")); + ASSERT_EQ(0, bstr_cmp_c_nocasenorzero(h->value, "BEFOREAFTER")); break; } @@ -1570,7 +1570,7 @@ htp_header_t *h = (htp_header_t *) htp_table_get_c(tx->request_headers, "Header-With-NUL"); ASSERT_TRUE(h != NULL); - ASSERT_EQ(0, bstr_cmp_c(h->value, "BEFORE")); + ASSERT_EQ(0, bstr_cmp_c_nocasenorzero(h->value, "BEFORE AFTER")); } TEST_F(ConnectionParsing, TestGenericPersonality) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libhtp-0.5.39/test/test_utils.cpp new/libhtp-0.5.40/test/test_utils.cpp --- old/libhtp-0.5.39/test/test_utils.cpp 2021-11-16 11:36:34.000000000 +0100 +++ new/libhtp-0.5.40/test/test_utils.cpp 2022-04-21 07:58:30.000000000 +0200 @@ -43,17 +43,6 @@ #include <gtest/gtest.h> #include <htp/htp_private.h> -TEST(Utf8, SingleByte) { - uint32_t state = HTP_UTF8_ACCEPT; - uint32_t codep; - uint32_t result; - - result = htp_utf8_decode(&state, &codep, 0x00); - EXPECT_EQ(0, result); - EXPECT_EQ(HTP_UTF8_ACCEPT, state); - EXPECT_EQ(0, codep); -} - TEST(Base64, Single) { EXPECT_EQ(62, htp_base64_decode_single('+')); EXPECT_EQ(63, htp_base64_decode_single('/'));
