diff options
-rw-r--r-- | debian/libwireshark0.symbols | 3 | ||||
-rw-r--r-- | debian/libwsutil0.symbols | 3 | ||||
-rw-r--r-- | epan/dissectors/packet-cups.c | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-irc.c | 41 | ||||
-rw-r--r-- | epan/dissectors/packet-megaco.c | 13 | ||||
-rw-r--r-- | epan/dissectors/packet-sdp.c | 12 | ||||
-rw-r--r-- | epan/dissectors/packet-sip.c | 49 | ||||
-rw-r--r-- | epan/tvbuff-int.h | 2 | ||||
-rw-r--r-- | epan/tvbuff.c | 56 | ||||
-rw-r--r-- | epan/tvbuff.h | 11 | ||||
-rw-r--r-- | epan/tvbuff_subset.c | 4 | ||||
-rw-r--r-- | frame_tvbuff.c | 4 | ||||
-rw-r--r-- | wsutil/ws_mempbrk.c | 60 | ||||
-rw-r--r-- | wsutil/ws_mempbrk.h | 27 | ||||
-rw-r--r-- | wsutil/ws_mempbrk_sse42.c | 123 |
15 files changed, 222 insertions, 194 deletions
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index f9e56c1fa5..f11eb99082 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -1374,7 +1374,8 @@ libwireshark.so.0 libwireshark0 #MINVER# tvb_new_subset_remaining@Base 1.9.1 tvb_offset_exists@Base 1.9.1 tvb_offset_from_real_beginning@Base 1.9.1 - tvb_pbrk_guint8@Base 1.9.1 + tvb_pbrk_compile@Base 1.99.2 + tvb_pbrk_pattern_guint8@Base 1.99.2 tvb_raw_offset@Base 1.9.1 tvb_reported_length@Base 1.9.1 tvb_reported_length_remaining@Base 1.9.1 diff --git a/debian/libwsutil0.symbols b/debian/libwsutil0.symbols index 281afa9265..34ad60ea32 100644 --- a/debian/libwsutil0.symbols +++ b/debian/libwsutil0.symbols @@ -141,6 +141,8 @@ libwsutil.so.0 libwsutil0 #MINVER# started_with_special_privs@Base 1.10.0 test_for_directory@Base 1.12.0~rc1 test_for_fifo@Base 1.12.0~rc1 + tvb_pbrk_compile@Base 1.99.3 + tvb_pbrk_exec@Base 1.99.3 type_util_gdouble_to_guint64@Base 1.10.0 type_util_guint64_to_gdouble@Base 1.10.0 u3_active@Base 1.12.0~rc1 @@ -162,6 +164,5 @@ libwsutil.so.0 libwsutil0 #MINVER# ws_buffer_free@Base 1.99.0 ws_buffer_init@Base 1.99.0 ws_buffer_remove_start@Base 1.99.0 - ws_mempbrk@Base 1.99.0 ws_utf8_char_len@Base 1.12.0~rc1 ws_xton@Base 1.12.0~rc1 diff --git a/epan/dissectors/packet-cups.c b/epan/dissectors/packet-cups.c index 1414548fbf..255bf970c5 100644 --- a/epan/dissectors/packet-cups.c +++ b/epan/dissectors/packet-cups.c @@ -103,6 +103,9 @@ static int hf_cups_make_model = -1; static gint ett_cups = -1; static gint ett_cups_ptype = -1; +/* patterns used for tvb_pbrk_pattern_guint8 */ +static tvb_pbrk_pattern pbrk_whitespace = INIT_PBRK_PATTERN; + /* This protocol is heavily related to IPP, but it is CUPS-specific and non-standard. */ #define UDP_PORT_CUPS 631 @@ -286,7 +289,7 @@ get_unquoted_string(tvbuff_t *tvb, gint offset, gint *next_offset, guint *len) guint l = 0; gint o; - o = tvb_pbrk_guint8(tvb, offset, -1, " \t\r\n", NULL); + o = tvb_pbrk_pattern_guint8(tvb, offset, -1, &pbrk_whitespace, NULL); if (o != -1) { l = o - offset; s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII); @@ -389,6 +392,9 @@ proto_register_cups(void) "CUPS", "cups"); proto_register_field_array(proto_cups, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); + + /* compile patterns */ + tvb_pbrk_compile(&pbrk_whitespace, " \t\r\n"); } void diff --git a/epan/dissectors/packet-irc.c b/epan/dissectors/packet-irc.c index fcf7f12d84..de201c235e 100644 --- a/epan/dissectors/packet-irc.c +++ b/epan/dissectors/packet-irc.c @@ -75,6 +75,8 @@ static expert_field ei_irc_tag_data_invalid = EI_INIT; /* This must be a null-terminated string */ static const guint8 TAG_DELIMITER[] = {0x01, 0x00}; +/* patterns used for tvb_pbrk_pattern_guint8 */ +static tvb_pbrk_pattern pbrk_tag_delimiter = INIT_PBRK_PATTERN; #define TCP_PORT_IRC 6667 @@ -88,14 +90,14 @@ dissect_irc_tag_data(proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offs found_end_needle = 0; gint tag_start_offset, tag_end_offset; - tag_start_offset = tvb_pbrk_guint8(tvb, offset, datalen, TAG_DELIMITER, &found_start_needle); + tag_start_offset = tvb_pbrk_pattern_guint8(tvb, offset, datalen, &pbrk_tag_delimiter, &found_start_needle); if (tag_start_offset == -1) { /* no tag data */ return; } - tag_end_offset = tvb_pbrk_guint8(tvb, offset, datalen-offset, TAG_DELIMITER, &found_end_needle); + tag_end_offset = tvb_pbrk_pattern_guint8(tvb, offset, datalen-offset, &pbrk_tag_delimiter, &found_end_needle); if (tag_end_offset == -1) { expert_add_info(pinfo, item, &ei_irc_missing_end_delimiter); @@ -124,8 +126,7 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off eocp_offset, tag_start_offset, tag_end_offset; guint8* str_command; - guchar found_needle = 0, - found_tag_needle = 0; + guchar found_tag_needle = 0; gboolean first_command_param = TRUE; request_item = proto_tree_add_item(tree, hf_irc_request, tvb, offset, linelen, ENC_ASCII|ENC_NA); @@ -138,7 +139,7 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off if (tvb_get_guint8(tvb, offset) == ':') { /* find the end of the prefix */ - eop_offset = tvb_pbrk_guint8(tvb, offset+1, linelen-1, " ", &found_needle); + eop_offset = tvb_find_guint8(tvb, offset+1, linelen-1, ' '); if (eop_offset == -1) { expert_add_info(pinfo, request_item, &ei_irc_prefix_missing_ending_space); @@ -146,7 +147,6 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off } proto_tree_add_item(request_tree, hf_irc_request_prefix, tvb, offset+1, eop_offset-offset-1, ENC_ASCII|ENC_NA); - found_needle = 0; offset = eop_offset+1; } @@ -161,7 +161,7 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off return; } - eoc_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle); + eoc_offset = tvb_find_guint8(tvb, offset, end_offset-offset, ' '); if (eoc_offset == -1) { proto_tree_add_item(request_tree, hf_irc_request_command, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA); @@ -192,7 +192,6 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off expert_add_info(pinfo, request_item, &ei_irc_numeric_request_command); } - found_needle = 0; offset = eoc_offset+1; /* clear out any whitespace before command parameter */ @@ -216,8 +215,8 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off while(offset < end_offset) { - eocp_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle); - tag_start_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, TAG_DELIMITER, &found_tag_needle); + eocp_offset = tvb_find_guint8(tvb, offset, end_offset-offset, ' '); + tag_start_offset = tvb_pbrk_pattern_guint8(tvb, offset, end_offset-offset, &pbrk_tag_delimiter, &found_tag_needle); /* Create subtree when the first parameter is found */ if (first_command_param) @@ -233,7 +232,6 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off { /* regular message should be dissected */ - found_needle = 0; if (eocp_offset == -1) { proto_tree_add_item(command_tree, hf_irc_request_command_param, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA); @@ -267,7 +265,7 @@ dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int off /* tag data dissected */ found_tag_needle = 0; - tag_end_offset = tvb_pbrk_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, TAG_DELIMITER, &found_tag_needle); + tag_end_offset = tvb_pbrk_pattern_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, &pbrk_tag_delimiter, &found_tag_needle); if (tag_end_offset == -1) { expert_add_info(pinfo, request_item, &ei_irc_missing_end_delimiter); @@ -293,8 +291,7 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of tag_start_offset, tag_end_offset; guint8* str_command; guint16 num_command; - guchar found_needle = 0, - found_tag_needle = 0; + guchar found_tag_needle = 0; gboolean first_command_param = TRUE; response_item = proto_tree_add_item(tree, hf_irc_response, tvb, offset, linelen, ENC_ASCII|ENC_NA); @@ -307,7 +304,7 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of if (tvb_get_guint8(tvb, offset) == ':') { /* find the end of the prefix */ - eop_offset = tvb_pbrk_guint8(tvb, offset+1, linelen-1, " ", &found_needle); + eop_offset = tvb_find_guint8(tvb, offset+1, linelen-1, ' '); if (eop_offset == -1) { expert_add_info(pinfo, response_item, &ei_irc_prefix_missing_ending_space); @@ -315,7 +312,6 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of } proto_tree_add_item(response_tree, hf_irc_response_prefix, tvb, offset+1, eop_offset-offset-1, ENC_ASCII|ENC_NA); - found_needle = 0; offset = eop_offset+1; } @@ -330,7 +326,7 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of return; } - eoc_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle); + eoc_offset = tvb_find_guint8(tvb, offset, end_offset-offset, ' '); if (eoc_offset == -1) { proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA); @@ -365,7 +361,6 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of PROTO_ITEM_SET_HIDDEN(hidden_item); } - found_needle = 0; offset = eoc_offset+1; /* clear out any whitespace before command parameter */ @@ -389,8 +384,8 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of while(offset < end_offset) { - eocp_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle); - tag_start_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, TAG_DELIMITER, &found_tag_needle); + eocp_offset = tvb_find_guint8(tvb, offset, end_offset-offset, ' '); + tag_start_offset = tvb_pbrk_pattern_guint8(tvb, offset, end_offset-offset, &pbrk_tag_delimiter, &found_tag_needle); /* Create subtree when the first parameter is found */ if (first_command_param) @@ -404,7 +399,6 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of { /* regular message should be dissected */ - found_needle = 0; if (eocp_offset == -1) { proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA); @@ -437,7 +431,7 @@ dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int of /* tag data dissected */ found_tag_needle = 0; - tag_end_offset = tvb_pbrk_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, TAG_DELIMITER, &found_tag_needle); + tag_end_offset = tvb_pbrk_pattern_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, &pbrk_tag_delimiter, &found_tag_needle); if (tag_end_offset == -1) { expert_add_info(pinfo, response_item, &ei_irc_missing_end_delimiter); @@ -567,6 +561,9 @@ proto_register_irc(void) proto_register_subtree_array(ett, array_length(ett)); expert_irc = expert_register_protocol(proto_irc); expert_register_field_array(expert_irc, ei, array_length(ei)); + + /* compile patterns */ + tvb_pbrk_compile(&pbrk_tag_delimiter, TAG_DELIMITER); } void diff --git a/epan/dissectors/packet-megaco.c b/epan/dissectors/packet-megaco.c index b80ed25505..84bd157f56 100644 --- a/epan/dissectors/packet-megaco.c +++ b/epan/dissectors/packet-megaco.c @@ -139,6 +139,11 @@ static dissector_handle_t megaco_text_handle; static int megaco_tap = -1; +/* patterns used for tvb_pbrk_pattern_guint8 */ +static tvb_pbrk_pattern pbrk_whitespace = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_braces = INIT_PBRK_PATTERN; + + /* * Here are the global variables associated with * the various user definable characteristics of the dissection @@ -451,7 +456,7 @@ dissect_megaco_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) * pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )["@" pathDomainName ] */ - tvb_current_offset = tvb_pbrk_guint8(tvb, tvb_current_offset, -1, " \t\r\n", &needle); + tvb_current_offset = tvb_pbrk_pattern_guint8(tvb, tvb_current_offset, -1, &pbrk_whitespace, &needle); if (tvb_current_offset == -1) { expert_add_info_format(pinfo, ti, &ei_megaco_parse_error, "[ Parse error: no body in MEGACO message (missing SEP after mId) ]"); @@ -3284,7 +3289,7 @@ static gint megaco_tvb_find_token(tvbuff_t* tvb, gint offset, gint maxlength){ guchar needle; do { - pos = tvb_pbrk_guint8(tvb, pos + 1, maxlength, "{}", &needle); + pos = tvb_pbrk_pattern_guint8(tvb, pos + 1, maxlength, &pbrk_braces, &needle); if(pos == -1) return -1; switch(needle){ @@ -3564,6 +3569,10 @@ proto_register_megaco(void) megaco_tap = register_tap("megaco"); + /* compile patterns */ + tvb_pbrk_compile(&pbrk_whitespace, " \t\r\n"); + tvb_pbrk_compile(&pbrk_braces, "{}"); + } /* Register all the bits needed with the filtering engine */ diff --git a/epan/dissectors/packet-sdp.c b/epan/dissectors/packet-sdp.c index 6b77ae924c..cf7897dda7 100644 --- a/epan/dissectors/packet-sdp.c +++ b/epan/dissectors/packet-sdp.c @@ -197,6 +197,10 @@ static expert_field ei_sdp_invalid_line_fields = EI_INIT; static expert_field ei_sdp_invalid_line_space = EI_INIT; static expert_field ei_sdp_invalid_conversion = EI_INIT; +/* patterns used for tvb_pbrk_pattern_guint8 */ +static tvb_pbrk_pattern pbrk_digits = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_alpha = INIT_PBRK_PATTERN; + #define SDP_RTP_PROTO 0x00000001 #define SDP_SRTP_PROTO 0x00000002 #define SDP_T38_PROTO 0x00000004 @@ -821,7 +825,7 @@ static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, pr offset = next_offset + 1; if (strcmp((char*)field_name, "ipbcp") == 0) { - offset = tvb_pbrk_guint8(tvb, offset, -1,"0123456789", NULL); + offset = tvb_pbrk_pattern_guint8(tvb, offset, -1,&pbrk_digits, NULL); if (offset == -1) return; @@ -832,7 +836,7 @@ static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, pr proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); - offset = tvb_pbrk_guint8(tvb, offset, -1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL); + offset = tvb_pbrk_pattern_guint8(tvb, offset, -1,&pbrk_alpha, NULL); if (offset == -1) return; @@ -3086,6 +3090,10 @@ proto_register_sdp(void) /* Register for tapping */ sdp_tap = register_tap("sdp"); + + /* compile patterns */ + tvb_pbrk_compile(&pbrk_digits, "0123456789"); + tvb_pbrk_compile(&pbrk_alpha, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } void diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c index ce59cec9a6..f34a157295 100644 --- a/epan/dissectors/packet-sip.c +++ b/epan/dissectors/packet-sip.c @@ -237,6 +237,18 @@ static expert_field ei_sip_header_not_terminated = EI_INIT; static expert_field ei_sip_odd_register_response = EI_INIT; static expert_field ei_sip_sipsec_malformed = EI_INIT; +/* patterns used for tvb_pbrk_pattern_guint8 */ +static tvb_pbrk_pattern pbrk_comma_semi = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_whitespace = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_param_end = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_param_end_colon_brackets = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_header_end_dquote = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_quotes = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_tab_sp_fslash = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_addr_end = INIT_PBRK_PATTERN; +static tvb_pbrk_pattern pbrk_via_param_end = INIT_PBRK_PATTERN; + + /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */ static const char *sip_methods[] = { #define SIP_METHOD_INVALID 0 @@ -1110,7 +1122,7 @@ dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset, */ int end_offset; - end_offset = tvb_pbrk_guint8(tvb, current_offset, line_end_offset - current_offset, ",;", NULL); + end_offset = tvb_pbrk_pattern_guint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_comma_semi, NULL); if (end_offset != -1) { @@ -1150,14 +1162,14 @@ dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset, while (parameter_end_offset < line_end_offset) { parameter_end_offset++; - parameter_end_offset = tvb_pbrk_guint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, ">,;? \r:[]", &c); + parameter_end_offset = tvb_pbrk_pattern_guint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, &pbrk_param_end_colon_brackets, &c); if (parameter_end_offset == -1) { parameter_end_offset = line_end_offset; break; } - /* after adding character to this switch() , update also string in tvb_pbrk_guint8() call above */ + /* after adding character to this switch() , update also pbrk_param_end_colon_brackets */ switch (c) { case '>': case ',': @@ -1196,14 +1208,14 @@ uri_host_end_found: while (parameter_end_offset < line_end_offset) { parameter_end_offset++; - parameter_end_offset = tvb_pbrk_guint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, ">,;? \r", &c); + parameter_end_offset = tvb_pbrk_pattern_guint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, &pbrk_param_end, &c); if (parameter_end_offset == -1) { parameter_end_offset = line_end_offset; break; } - /* after adding character to this switch(), update also string in tvb_pbrk_guint8() call above */ + /* after adding character to this switch(), update also pbrk_param_end */ switch (c) { case '>': case ',': @@ -1568,7 +1580,7 @@ display_sip_uri (tvbuff_t *tvb, proto_tree *sip_element_tree, packet_info *pinfo /* Put the contact parameters in the tree */ while (current_offset < uri_offsets->name_addr_end) { - queried_offset = tvb_pbrk_guint8(tvb, current_offset, uri_offsets->name_addr_end - current_offset, ",;", &c); + queried_offset = tvb_pbrk_pattern_guint8(tvb, current_offset, uri_offsets->name_addr_end - current_offset, &pbrk_comma_semi, &c); if (queried_offset == -1) { /* Reached line end */ @@ -1669,7 +1681,7 @@ dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gi while(current_offset< line_end_offset){ c = '\0'; queried_offset++; - queried_offset = (queried_offset < line_end_offset) ? tvb_pbrk_guint8(tvb, queried_offset, line_end_offset - queried_offset, "\r\n,;\"", &c) : -1; + queried_offset = (queried_offset < line_end_offset) ? tvb_pbrk_pattern_guint8(tvb, queried_offset, line_end_offset - queried_offset, &pbrk_header_end_dquote, &c) : -1; if (queried_offset != -1) { switch (c) { @@ -1698,7 +1710,7 @@ dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gi /* We have an opening quote but no closing quote. */ current_offset = line_end_offset; } else { - current_offset = tvb_pbrk_guint8(tvb, queried_offset+1, line_end_offset - queried_offset, ",;", &c); + current_offset = tvb_pbrk_pattern_guint8(tvb, queried_offset+1, line_end_offset - queried_offset, &pbrk_comma_semi, &c); if(current_offset==-1){ /* Last parameter, line end */ current_offset = line_end_offset; @@ -1797,7 +1809,7 @@ dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offse name = tvb_get_string_enc(wmem_packet_scope(), tvb, start_offset, par_name_end_offset-start_offset, ENC_UTF_8|ENC_NA); /* Find end of parameter, it can be a quoted string so check for quoutes too */ - queried_offset = tvb_pbrk_guint8(tvb, par_name_end_offset, line_end_offset - par_name_end_offset, "'\"", &c); + queried_offset = tvb_pbrk_pattern_guint8(tvb, par_name_end_offset, line_end_offset - par_name_end_offset, &pbrk_quotes, &c); if (queried_offset == -1) { /* Last parameter, line end */ current_offset = line_end_offset; @@ -2166,7 +2178,7 @@ static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_o { int transport_start_offset = current_offset; - current_offset = tvb_pbrk_guint8(tvb, current_offset, line_end_offset - current_offset, "\t /", &c); + current_offset = tvb_pbrk_pattern_guint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_tab_sp_fslash, &c); if (current_offset != -1){ proto_tree_add_item(tree, hf_sip_via_transport, tvb, transport_start_offset, current_offset - transport_start_offset, ENC_UTF_8|ENC_NA); @@ -2195,7 +2207,7 @@ static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_o address_start_offset = current_offset; while (current_offset < line_end_offset) { - current_offset = tvb_pbrk_guint8(tvb, current_offset, line_end_offset - current_offset, "[] \t:;", &c); + current_offset = tvb_pbrk_pattern_guint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_addr_end, &c); if (current_offset == -1) { current_offset = line_end_offset; @@ -2330,7 +2342,7 @@ static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_o parameter_name_end = current_offset; /* Read until end of parameter value */ - current_offset = tvb_pbrk_guint8(tvb, current_offset, line_end_offset - current_offset, "\t;, ", NULL); + current_offset = tvb_pbrk_pattern_guint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_via_param_end, NULL); if (current_offset == -1) current_offset = line_end_offset; @@ -3407,7 +3419,7 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info if (hf_index != POS_AUTHENTICATION_INFO) { /* The first time comma_offset is "start of parameters" */ - comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n", NULL); + comma_offset = tvb_pbrk_pattern_guint8(tvb, value_offset, line_end_offset - value_offset, &pbrk_whitespace, NULL); proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme, tvb, value_offset, comma_offset - value_offset, ENC_UTF_8|ENC_NA); @@ -5946,6 +5958,17 @@ void proto_register_sip(void) ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", FT_STRING, BASE_NONE); + /* compile patterns */ + tvb_pbrk_compile(&pbrk_comma_semi, ",;"); + tvb_pbrk_compile(&pbrk_whitespace, " \t\r\n"); + tvb_pbrk_compile(&pbrk_param_end, ">,;? \r"); + tvb_pbrk_compile(&pbrk_param_end_colon_brackets, ">,;? \r:[]"); + tvb_pbrk_compile(&pbrk_header_end_dquote, "\r\n,;\""); + tvb_pbrk_compile(&pbrk_quotes, "'\""); + tvb_pbrk_compile(&pbrk_tab_sp_fslash, "\t /"); + tvb_pbrk_compile(&pbrk_addr_end, "[] \t:;"); + tvb_pbrk_compile(&pbrk_via_param_end, "\t;, "); + } void diff --git a/epan/tvbuff-int.h b/epan/tvbuff-int.h index 7c8d29eef3..c925863e88 100644 --- a/epan/tvbuff-int.h +++ b/epan/tvbuff-int.h @@ -34,7 +34,7 @@ struct tvb_ops { void *(*tvb_memcpy)(struct tvbuff *tvb, void *target, guint offset, guint length); gint (*tvb_find_guint8)(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle); - gint (*tvb_pbrk_guint8)(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle); + gint (*tvb_pbrk_pattern_guint8)(tvbuff_t *tvb, guint abs_offset, guint limit, const tvb_pbrk_pattern* pattern, guchar *found_needle); tvbuff_t *(*tvb_clone)(tvbuff_t *tvb, guint abs_offset, guint abs_length); }; diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 95e7548608..d37859acbc 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -44,7 +44,6 @@ #include "wsutil/unicode-utils.h" #include "wsutil/nstime.h" #include "wsutil/time_util.h" -#include "wsutil/ws_mempbrk.h" #include "tvbuff.h" #include "tvbuff-int.h" #include "strutil.h" @@ -755,17 +754,6 @@ fast_ensure_contiguous(tvbuff_t *tvb, const gint offset, const guint length) return NULL; } -static inline const guint8* -guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, guchar *found_needle) -{ - const guint8 *result = ws_mempbrk(haystack, haystacklen, needles); - - if (result && found_needle) - *found_needle = *result; - - return result; -} - /************** ACCESSORS **************/ @@ -1906,21 +1894,22 @@ tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu } static inline gint -tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle) +tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const tvb_pbrk_pattern* pattern, guchar *found_needle) { const guint8 *ptr; const guint8 *result; ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr */ - result = guint8_pbrk(ptr, limit, needles, found_needle); + result = tvb_pbrk_exec(ptr, limit, pattern, found_needle); if (!result) return -1; return (gint) ((result - ptr) + abs_offset); } -/* Find first occurrence of any of the needles in tvbuff, starting at offset. + +/* Find first occurrence of any of the pattern chars in tvbuff, starting at offset. * Searches at most maxlength number of bytes; if maxlength is -1, searches * to end of tvbuff. * Returns the offset of the found needle, or -1 if not found. @@ -1928,7 +1917,8 @@ tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const guin * in that case, -1 will be returned if the boundary is reached before * finding needle. */ gint -tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 *needles, guchar *found_needle) +tvb_pbrk_pattern_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, + const tvb_pbrk_pattern* pattern, guchar *found_needle) { const guint8 *result; guint abs_offset; @@ -1950,7 +1940,7 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu /* If we have real data, perform our search now. */ if (tvb->real_data) { - result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles, found_needle); + result = tvb_pbrk_exec(tvb->real_data + abs_offset, limit, pattern, found_needle); if (result == NULL) { return -1; } @@ -1959,10 +1949,10 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu } } - if (tvb->ops->tvb_pbrk_guint8) - return tvb->ops->tvb_pbrk_guint8(tvb, abs_offset, limit, needles, found_needle); + if (tvb->ops->tvb_pbrk_pattern_guint8) + return tvb->ops->tvb_pbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle); - return tvb_pbrk_guint8_generic(tvb, abs_offset, limit, needles, found_needle); + return tvb_pbrk_guint8_generic(tvb, abs_offset, limit, pattern, found_needle); } /* Find size of stringz (NUL-terminated string) by looking for terminating @@ -3048,6 +3038,8 @@ tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* } } + +static tvb_pbrk_pattern pbrk_crlf = INIT_PBRK_PATTERN; /* * Given a tvbuff, an offset into the tvbuff, and a length that starts * at that offset (which may be -1 for "all the way to the end of the @@ -3070,16 +3062,11 @@ tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* gint tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset, const gboolean desegment) { -#ifdef WIN32 - static const char __declspec(align(16)) crlf[] = "\r\n" ; -#else - static const char crlf[] __attribute__((aligned(16))) = "\r\n" ; -#endif - gint eob_offset; gint eol_offset; int linelen; guchar found_needle = 0; + static gboolean compiled = FALSE; DISSECTOR_ASSERT(tvb && tvb->initialized); @@ -3091,10 +3078,15 @@ tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset, */ eob_offset = offset + len; + if (!compiled) { + tvb_pbrk_compile(&pbrk_crlf, "\r\n"); + compiled = TRUE; + } + /* * Look either for a CR or an LF. */ - eol_offset = tvb_pbrk_guint8(tvb, offset, len, crlf, &found_needle); + eol_offset = tvb_pbrk_pattern_guint8(tvb, offset, len, &pbrk_crlf, &found_needle); if (eol_offset == -1) { /* * No CR or LF - line is presumably continued in next packet. @@ -3172,6 +3164,7 @@ tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset, return linelen; } +static tvb_pbrk_pattern pbrk_crlf_dquote = INIT_PBRK_PATTERN; /* * Given a tvbuff, an offset into the tvbuff, and a length that starts * at that offset (which may be -1 for "all the way to the end of the @@ -3198,11 +3191,18 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len, gint *next guchar c = 0; gint eob_offset; int linelen; + static gboolean compiled = FALSE; DISSECTOR_ASSERT(tvb && tvb->initialized); if (len == -1) len = _tvb_captured_length_remaining(tvb, offset); + + if (!compiled) { + tvb_pbrk_compile(&pbrk_crlf_dquote, "\r\n\""); + compiled = TRUE; + } + /* * XXX - what if "len" is still -1, meaning "offset is past the * end of the tvbuff"? @@ -3225,7 +3225,7 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len, gint *next /* * Look either for a CR, an LF, or a '"'. */ - char_offset = tvb_pbrk_guint8(tvb, cur_offset, len, "\r\n\"", &c); + char_offset = tvb_pbrk_pattern_guint8(tvb, cur_offset, len, &pbrk_crlf_dquote, &c); } if (char_offset == -1) { /* diff --git a/epan/tvbuff.h b/epan/tvbuff.h index 4a72b542a3..c5936020f2 100644 --- a/epan/tvbuff.h +++ b/epan/tvbuff.h @@ -36,6 +36,7 @@ #include <glib.h> #include <epan/guid-utils.h> #include <epan/wmem/wmem.h> +#include "wsutil/ws_mempbrk.h" #ifdef __cplusplus extern "C" { @@ -505,14 +506,18 @@ WS_DLL_PUBLIC const guint8 *tvb_get_ptr(tvbuff_t *tvb, const gint offset, WS_DLL_PUBLIC gint tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 needle); -/** Find first occurrence of any of the needles in tvbuff, starting at offset. + +/** Find first occurrence of any of the needles of the pre-compiled pattern in + * tvbuff, starting at offset. The passed in pattern must have been "compiled" + * before-hand, using tvb_pbrk_compile() above. * Searches at most maxlength number of bytes. Returns the offset of the * found needle, or -1 if not found and the found needle. * Will not throw an exception, even if * maxlength exceeds boundary of tvbuff; in that case, -1 will be returned if * the boundary is reached before finding needle. */ -WS_DLL_PUBLIC gint tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, - const gint maxlength, const guint8 *needles, guchar *found_needle); +WS_DLL_PUBLIC gint tvb_pbrk_pattern_guint8(tvbuff_t *tvb, const gint offset, + const gint maxlength, const tvb_pbrk_pattern* pattern, guchar *found_needle); + /** Find size of stringz (NUL-terminated string) by looking for terminating * NUL. The size of the string includes the terminating NUL. diff --git a/epan/tvbuff_subset.c b/epan/tvbuff_subset.c index fbfe48af1c..8db4c0f510 100644 --- a/epan/tvbuff_subset.c +++ b/epan/tvbuff_subset.c @@ -79,11 +79,11 @@ subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle) } static gint -subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle) +subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const tvb_pbrk_pattern* pattern, guchar *found_needle) { struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb; - return tvb_pbrk_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needles, found_needle); + return tvb_pbrk_pattern_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, pattern, found_needle); } static tvbuff_t * diff --git a/frame_tvbuff.c b/frame_tvbuff.c index cc02722283..d70b053cae 100644 --- a/frame_tvbuff.c +++ b/frame_tvbuff.c @@ -139,13 +139,13 @@ frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle) } static gint -frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle) +frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const tvb_pbrk_pattern* pattern, guchar *found_needle) { struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; frame_cache(frame_tvb); - return tvb_pbrk_guint8(tvb, abs_offset, limit, needles, found_needle); + return tvb_pbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle); } static guint diff --git a/wsutil/ws_mempbrk.c b/wsutil/ws_mempbrk.c index 8ad1a17e78..6ed9ebcd9e 100644 --- a/wsutil/ws_mempbrk.c +++ b/wsutil/ws_mempbrk.c @@ -36,50 +36,54 @@ #include <glib.h> #include "ws_symbol_export.h" +#include "ws_mempbrk.h" + + +void +tvb_pbrk_compile(tvb_pbrk_pattern* pattern, const gchar *needles) +{ + const gchar *n = needles; + while (*n) { + pattern->patt[(int)*n] = 1; + n++; + } + #ifdef HAVE_SSE4_2 -#include "ws_cpuid.h" + ws_mempbrk_sse42_compile(pattern, needles); #endif -#include "ws_mempbrk.h" +} + const guint8 * -_ws_mempbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles) +ws_mempbrk_exec(const guint8* haystack, size_t haystacklen, const tvb_pbrk_pattern* pattern, guchar *found_needle) { - gchar tmp[256] = { 0 }; - const guint8 *haystack_end; + const guint8 *haystack_end = haystack + haystacklen; - while (*needles) - tmp[*needles++] = 1; + while (haystack < haystack_end) { + if (pattern->patt[*haystack]) { + if (found_needle) + *found_needle = *haystack; + return haystack; + } + haystack++; + } - haystack_end = haystack + haystacklen; - while (haystack < haystack_end) { - if (tmp[*haystack]) - return haystack; - haystack++; - } - - return NULL; + return NULL; } + WS_DLL_PUBLIC const guint8 * -ws_mempbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles) +tvb_pbrk_exec(const guint8* haystack, size_t haystacklen, const tvb_pbrk_pattern* pattern, guchar *found_needle) { #ifdef HAVE_SSE4_2 - static int have_sse42 = -1; + if (haystacklen >= 16 && pattern->use_sse42) + return ws_mempbrk_sse42_exec(haystack, haystacklen, pattern, found_needle); #endif - if (*needles == 0) - return NULL; - -#ifdef HAVE_SSE4_2 - if G_UNLIKELY(have_sse42 < 0) - have_sse42 = ws_cpuid_sse42(); - if (haystacklen >= 16 && have_sse42) - return _ws_mempbrk_sse42(haystack, haystacklen, needles); -#endif - - return _ws_mempbrk(haystack, haystacklen, needles); + return ws_mempbrk_exec(haystack, haystacklen, pattern, found_needle); } + /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * diff --git a/wsutil/ws_mempbrk.h b/wsutil/ws_mempbrk.h index 72f37d574a..708d53cfff 100644 --- a/wsutil/ws_mempbrk.h +++ b/wsutil/ws_mempbrk.h @@ -24,13 +24,30 @@ #include "ws_symbol_export.h" -WS_DLL_PUBLIC const guint8 *ws_mempbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles); +/** The pattern object used for tvb_pbrk_pattern_guint8(). + */ +typedef struct { + gchar patt[256]; + gboolean use_sse42; + void *mask; +} tvb_pbrk_pattern; + +/** The value to use when initializing a tvb_pbrk_pattern variable. + * For example: + * static tvb_pbrk_pattern pbrk_mypattern = INIT_PBRK_PATTERN; + */ +#define INIT_PBRK_PATTERN { { 0 }, FALSE, NULL } + +/** Compile the pattern for the needles to find using tvb_pbrk_pattern_guint8(). + */ +WS_DLL_PUBLIC void tvb_pbrk_compile(tvb_pbrk_pattern* pattern, const gchar *needles); + +WS_DLL_PUBLIC const guint8 *tvb_pbrk_exec(const guint8* haystack, size_t haystacklen, const tvb_pbrk_pattern* pattern, guchar *found_needle); -#ifdef HAVE_SSE4_2 -const char *_ws_mempbrk_sse42(const char* haystack, size_t haystacklen, const char *needles); -#endif +void ws_mempbrk_sse42_compile(tvb_pbrk_pattern* pattern, const gchar *needles); +const char *ws_mempbrk_sse42_exec(const char* haystack, size_t haystacklen, const tvb_pbrk_pattern* pattern, guchar *found_needle); -const guint8 *_ws_mempbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles); +const guint8 *ws_mempbrk_exec(const guint8* haystack, size_t haystacklen, const tvb_pbrk_pattern* pattern, guchar *found_needle); #endif /* __WS_MEMPBRK_H__ */ diff --git a/wsutil/ws_mempbrk_sse42.c b/wsutil/ws_mempbrk_sse42.c index 2805c0240e..da37a665aa 100644 --- a/wsutil/ws_mempbrk_sse42.c +++ b/wsutil/ws_mempbrk_sse42.c @@ -23,7 +23,7 @@ #ifdef HAVE_SSE4_2 #include <glib.h> - +#include "ws_cpuid.h" #ifdef WIN32 #include <tmmintrin.h> @@ -59,6 +59,23 @@ __m128i_shift_right (__m128i value, unsigned long int offset) _mm_loadu_si128 (cast_128aligned__m128i(___m128i_shift_right + offset))); } + +void +ws_mempbrk_sse42_compile(tvb_pbrk_pattern* pattern, const gchar *needles) +{ + size_t length = strlen(needles); + + pattern->use_sse42 = ws_cpuid_sse42() && (length <= 16); + + if (pattern->use_sse42) { + __m128i *pmask = NULL; + pattern->mask = g_malloc(sizeof(__m128i)); + pmask = (__m128i *) pattern->mask; + *pmask = _mm_setzero_si128(); + memcpy(pmask, needles, length); + } +} + /* We use 0x2: _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY @@ -92,81 +109,12 @@ __m128i_shift_right (__m128i value, unsigned long int offset) X for case 1. */ const char * -_ws_mempbrk_sse42(const char *s, size_t slen, const char *a) +ws_mempbrk_sse42_exec(const char *s, size_t slen, const tvb_pbrk_pattern* pattern, guchar *found_needle) { const char *aligned; - __m128i mask; + __m128i *pmask = (__m128i *) pattern->mask; int offset; -#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) - { - /* As 'a' is not guarantueed to have a size of at least 16 bytes, and is not - * aligned, _mm_load_si128() cannot be used when ASAN is enabled. That - * triggers a buffer overflow which is harmless as 'a' is guaranteed to be - * '\0' terminated, and the PCMISTRI instruction always ignored everything - * starting from EOS ('\0'). A false positive indeed. */ - size_t length; - - length = strlen(a); - /* Don't use SSE4.2 if the length of A > 16. */ - if (length > 16) - return _ws_mempbrk(s, slen, a); - - mask = _mm_setzero_si128(); - memcpy(&mask, a, length); - } -#else /* else if ASAN is disabled */ - offset = (int) ((size_t) a & 15); - aligned = (const char *) ((size_t) a & -16L); - if (offset != 0) - { - int length; - - /* Load masks. */ - /* cast safe - _mm_load_si128() it's 16B aligned */ - mask = __m128i_shift_right(_mm_load_si128 (cast_128aligned__m128i(aligned)), offset); - - /* Find where the NULL terminator is. */ - length = _mm_cmpistri (mask, mask, 0x3a); - if (length == 16 - offset) - { - /* There is no NULL terminator. */ - __m128i mask1 = _mm_load_si128 (cast_128aligned__m128i(aligned + 16)); - int idx = _mm_cmpistri (mask1, mask1, 0x3a); - length += idx; - - /* Don't use SSE4.2 if the length of A > 16. */ - if (length > 16) - return _ws_mempbrk(s, slen, a); - - if (idx != 0) - { - /* Combine mask0 and mask1. We could play games with - palignr, but frankly this data should be in L1 now - so do the merge via an unaligned load. */ - mask = _mm_loadu_si128 (cast_128aligned__m128i(a)); - } - } - } - else - { - int length; - - /* A is aligned. (cast safe) */ - mask = _mm_load_si128 (cast_128aligned__m128i(a)); - - /* Find where the NULL terminator is. */ - length = _mm_cmpistri (mask, mask, 0x3a); - if (length == 16) - { - /* There is no NULL terminator. Don't use SSE4.2 if the length - of A > 16. */ - if (a[16] != 0) - return _ws_mempbrk(s, slen, a); - } - } -#endif /* ASAN disabled */ - offset = (int) ((size_t) s & 15); aligned = (const char *) ((size_t) s & -16L); if (offset != 0) @@ -174,18 +122,23 @@ _ws_mempbrk_sse42(const char *s, size_t slen, const char *a) /* Check partial string. cast safe it's 16B aligned */ __m128i value = __m128i_shift_right (_mm_load_si128 (cast_128aligned__m128i(aligned)), offset); - int length = _mm_cmpistri (mask, value, 0x2); + int length = _mm_cmpistri (*pmask, value, 0x2); /* No need to check ZFlag since ZFlag is always 1. */ - int cflag = _mm_cmpistrc (mask, value, 0x2); + int cflag = _mm_cmpistrc (*pmask, value, 0x2); + /* XXX: why does this compare value with value? */ int idx = _mm_cmpistri (value, value, 0x3a); - if (cflag) + if (cflag) { + if (found_needle) + *found_needle = *(s + length); return s + length; + } + /* Find where the NULL terminator is. */ if (idx < 16 - offset) { - /* fond NUL @ 'idx', need to switch to slower mempbrk */ - return _ws_mempbrk(s + idx + 1, slen - idx - 1, a); /* slen is bigger than 16 & idx < 16 so no undeflow here */ + /* found NUL @ 'idx', need to switch to slower mempbrk */ + return ws_mempbrk_exec(s + idx + 1, slen - idx - 1, pattern, found_needle); /* slen is bigger than 16 & idx < 16 so no undeflow here */ } aligned += 16; slen -= (16 - offset); @@ -196,23 +149,27 @@ _ws_mempbrk_sse42(const char *s, size_t slen, const char *a) while (slen >= 16) { __m128i value = _mm_load_si128 (cast_128aligned__m128i(aligned)); - int idx = _mm_cmpistri (mask, value, 0x2); - int cflag = _mm_cmpistrc (mask, value, 0x2); - int zflag = _mm_cmpistrz (mask, value, 0x2); + int idx = _mm_cmpistri (*pmask, value, 0x2); + int cflag = _mm_cmpistrc (*pmask, value, 0x2); + int zflag = _mm_cmpistrz (*pmask, value, 0x2); - if (cflag) + if (cflag) { + if (found_needle) + *found_needle = *(aligned + idx); return aligned + idx; + } + if (zflag) { /* found NUL, need to switch to slower mempbrk */ - return _ws_mempbrk(aligned, slen, a); + return ws_mempbrk_exec(aligned, slen, pattern, found_needle); } aligned += 16; slen -= 16; } /* XXX, use mempbrk_slow here? */ - return _ws_mempbrk(aligned, slen, a); + return ws_mempbrk_exec(aligned, slen, pattern, found_needle); } #endif /* HAVE_SSE4_2 */ |