Move two functions from epan to wsutil/str_util

Move epan_memmem() and epan_strcasestr() to wsutil/str_util.
Rename to ws_memmem() and ws_strcasestr(). Add compile time
check for a system implementation and use that if available.

We invoke those functions using a wrapper to avoid exposing
_GNU_SOURCE outside of the implementation.
This commit is contained in:
João Valverde 2021-11-27 17:57:46 +00:00 committed by Wireshark GitLab Utility
parent ede0bc5d61
commit ef8125e3ae
12 changed files with 106 additions and 81 deletions

View File

@ -92,6 +92,13 @@ if (APPLE)
check_function_exists("CFPropertyListCreateWithStream" HAVE_CFPROPERTYLISTCREATEWITHSTREAM)
cmake_pop_check_state()
endif()
if(UNIX)
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
check_function_exists("memmem" HAVE_MEMMEM)
check_function_exists("strcasestr" HAVE_STRCASESTR)
cmake_pop_check_state()
endif()
#Struct members
include(CheckStructHasMember)

View File

@ -250,6 +250,12 @@
/* Define if you have the 'strptime' function. */
#cmakedefine HAVE_STRPTIME 1
/* Define if you have the 'memmem' function. */
#cmakedefine HAVE_MEMMEM 1
/* Define if you have the 'strcasestr' function. */
#cmakedefine HAVE_STRCASESTR 1
/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1

View File

@ -590,12 +590,10 @@ libwireshark.so.0 libwireshark0 #MINVER#
epan_inspect_enums_bsearch@Base 3.7.0
epan_inspect_enums_count@Base 3.7.0
epan_load_settings@Base 2.3.0
epan_memmem@Base 1.9.1
epan_new@Base 1.12.0~rc1
epan_plugins_supported@Base 3.5.0
epan_register_plugin@Base 2.5.0
epan_set_always_visible@Base 3.5.1
epan_strcasestr@Base 1.9.1
escape_string@Base 1.9.1
escape_string_len@Base 1.9.1
esp_sa_record_add_from_dissector@Base 1.12.0~rc1

View File

@ -399,6 +399,7 @@ libwsutil.so.0 libwsutil0 #MINVER#
ws_log_write_always_full@Base 3.5.0
ws_logv@Base 3.5.0
ws_logv_full@Base 3.5.0
ws_memmem@Base 3.7.0
ws_mempbrk_compile@Base 1.99.4
ws_mempbrk_exec@Base 1.99.4
ws_optarg@Base 3.5.1
@ -418,6 +419,7 @@ libwsutil.so.0 libwsutil0 #MINVER#
ws_regex_matches@Base 3.7.0
ws_regex_pattern@Base 3.7.0
ws_socket_ptoa@Base 3.1.1
ws_strcasestr@Base 3.7.0
ws_strtoi16@Base 2.3.0
ws_strtoi32@Base 2.3.0
ws_strtoi64@Base 2.3.0

View File

@ -230,8 +230,8 @@ dissect_k12(tvbuff_t* tvb,packet_info* pinfo,proto_tree* tree, void* data _U_)
if (! handles ) {
for (i=0 ; i < nk12_handles; i++) {
if ( epan_strcasestr(pinfo->pseudo_header->k12.stack_file, k12_handles[i].match)
|| epan_strcasestr(pinfo->pseudo_header->k12.input_name, k12_handles[i].match) ) {
if ( ws_strcasestr(pinfo->pseudo_header->k12.stack_file, k12_handles[i].match)
|| ws_strcasestr(pinfo->pseudo_header->k12.input_name, k12_handles[i].match) ) {
handles = k12_handles[i].handles;
break;
}

View File

@ -284,7 +284,7 @@ xmpp_unknown_attrs(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, xmpp
proto_tree_add_string(tree, hf_xmpp_xmlns, tvb, attr->offset, attr->length, attr->value);
else {
/*xmlns may looks like xmlns:abbrev="sth"*/
const gchar *xmlns_needle = epan_strcasestr((const char *)keys->data, "xmlns:");
const gchar *xmlns_needle = ws_strcasestr((const char *)keys->data, "xmlns:");
if (xmlns_needle && xmlns_needle == keys->data) {
proto_tree_add_string_format(tree, hf_xmpp_xmlns, tvb, attr->offset, attr->length, attr->value,"%s: %s", (gchar*)keys->data, attr->value);
} else {
@ -581,7 +581,7 @@ xmpp_xml_frame_to_element_t(wmem_allocator_t *pool, xml_frame_t *xml_frame, xmpp
g_hash_table_insert(node->attrs,(gpointer)attr->name,(gpointer)attr);
/*checking that attr->name looks like xmlns:ns*/
xmlns_needle = epan_strcasestr(attr->name, "xmlns");
xmlns_needle = ws_strcasestr(attr->name, "xmlns");
if(xmlns_needle == attr->name)
{
@ -654,7 +654,7 @@ attr_find_pred(gpointer key, gpointer value _U_, gpointer user_data)
if( strcmp(attr_name, "xmlns") == 0 )
{
const gchar *first_occur = epan_strcasestr((const char *)key, "xmlns:");
const gchar *first_occur = ws_strcasestr((const char *)key, "xmlns:");
if(first_occur && first_occur == key)
return TRUE;
else

View File

@ -545,7 +545,7 @@ cmp_contains(const fvalue_t *fv_a, const fvalue_t *fv_b)
GByteArray *a = fv_a->value.bytes;
GByteArray *b = fv_b->value.bytes;
if (epan_memmem(a->data, a->len, b->data, b->len)) {
if (ws_memmem(a->data, a->len, b->data, b->len)) {
return TRUE;
}
else {

View File

@ -1357,37 +1357,6 @@ xml_escape(const gchar *unescaped)
return g_string_free(buffer, FALSE);
}
/* Return the first occurrence of needle in haystack.
* If not found, return NULL.
* If either haystack or needle has 0 length, return NULL.
* Algorithm copied from GNU's glibc 2.3.2 memmem() under LGPL 2.1+ */
const guint8 *
epan_memmem(const guint8 *haystack, guint haystack_len,
const guint8 *needle, guint needle_len)
{
const guint8 *begin;
const guint8 *const last_possible = haystack + haystack_len - needle_len;
if (needle_len == 0) {
return NULL;
}
if (needle_len > haystack_len) {
return NULL;
}
for (begin = haystack ; begin <= last_possible; ++begin) {
if (begin[0] == needle[0] &&
!memcmp(&begin[1], needle + 1,
needle_len - 1)) {
return begin;
}
}
return NULL;
}
/*
* Scan the search string to make sure it's valid hex. Return the
* number of bytes in nbytes.
@ -1479,20 +1448,6 @@ convert_string_case(const char *string, gboolean case_insensitive)
}
}
const char *
epan_strcasestr(const char *haystack, const char *needle)
{
gsize hlen = strlen(haystack);
gsize nlen = strlen(needle);
while (hlen-- >= nlen) {
if (!g_ascii_strncasecmp(haystack, needle, nlen))
return haystack;
haystack++;
}
return NULL;
}
const char *
string_or_null(const char *string)
{

View File

@ -261,22 +261,6 @@ gboolean byte_array_equal(GByteArray *ba1, GByteArray *ba2);
WS_DLL_PUBLIC
gchar* xml_escape(const gchar *unescaped);
/**
* Return the first occurrence of needle in haystack.
* Algorithm copied from GNU's glibc 2.3.2 memcmp()
*
* @param haystack The data to search
* @param haystack_len The length of the search data
* @param needle The string to look for
* @param needle_len The length of the search string
* @return A pointer to the first occurrence of "needle" in
* "haystack". If "needle" isn't found or is NULL, or if
* "needle_len" is 0, NULL is returned.
*/
WS_DLL_PUBLIC
const guint8 * epan_memmem(const guint8 *haystack, guint haystack_len,
const guint8 *needle, guint needle_len);
/** Scan a string to make sure it's valid hex.
*
* @param string The string to validate
@ -298,17 +282,6 @@ guint8 * convert_string_to_hex(const char *string, size_t *nbytes);
WS_DLL_PUBLIC
char * convert_string_case(const char *string, gboolean case_insensitive);
/** Finds the first occurrence of string 'needle' in string 'haystack'.
* The matching is done in a case insensitive manner.
*
* @param haystack The string possibly containing the substring
* @param needle The substring to be searched
* @return A pointer into 'haystack' where 'needle' is first found.
* Otherwise it returns NULL.
*/
WS_DLL_PUBLIC
const char * epan_strcasestr(const char *haystack, const char *needle);
/** Guarantee a non-null string.
*
* @param string The string to check
@ -319,6 +292,7 @@ const char * string_or_null(const char *string);
WS_DLL_PUBLIC
int escape_string_len(const char *string);
WS_DLL_PUBLIC
char * escape_string(char *dst, const char *string);

View File

@ -4448,7 +4448,7 @@ tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const gint haystack_o
check_offset_length(haystack_tvb, haystack_offset, -1,
&haystack_abs_offset, &haystack_abs_length);
location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
location = ws_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
needle_data, needle_len);
if (location) {

View File

@ -8,9 +8,12 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#define _GNU_SOURCE
#include "config.h"
#include "str_util.h"
#include <string.h>
int
ws_xton(char ch)
{
@ -116,6 +119,60 @@ isdigit_string(const guchar *str)
return TRUE;
}
/* Return the first occurrence of needle in haystack.
* If not found, return NULL.
* If either haystack or needle has 0 length, return NULL.*/
const guint8 *
ws_memmem(const void *_haystack, size_t haystack_len,
const void *_needle, size_t needle_len)
{
#ifdef HAVE_MEMMEM
return memmem(_haystack, haystack_len, _needle, needle_len);
#else
/* Algorithm copied from GNU's glibc 2.3.2 memmem() under LGPL 2.1+ */
const guint8 *haystack = _haystack;
const guint8 *needle = _needle;
const guint8 *begin;
const guint8 *const last_possible = haystack + haystack_len - needle_len;
if (needle_len == 0) {
return NULL;
}
if (needle_len > haystack_len) {
return NULL;
}
for (begin = haystack ; begin <= last_possible; ++begin) {
if (begin[0] == needle[0] &&
!memcmp(&begin[1], needle + 1,
needle_len - 1)) {
return begin;
}
}
return NULL;
#endif /* HAVE_MEMMEM */
}
const char *
ws_strcasestr(const char *haystack, const char *needle)
{
#ifdef HAVE_STRCASESTR
return strcasestr(haystack, needle);
#else
gsize hlen = strlen(haystack);
gsize nlen = strlen(needle);
while (hlen-- >= nlen) {
if (!g_ascii_strncasecmp(haystack, needle, nlen))
return haystack;
haystack++;
}
return NULL;
#endif /* HAVE_STRCASESTR */
}
#define FORMAT_SIZE_UNIT_MASK 0x00ff
#define FORMAT_SIZE_PFX_MASK 0xff00

View File

@ -79,6 +79,32 @@ gboolean isprint_utf8_string(const gchar *str, guint length);
WS_DLL_PUBLIC
gboolean isdigit_string(const guchar *str);
/**
* Return the first occurrence of needle in haystack.
*
* @param haystack The data to search
* @param haystack_len The length of the search data
* @param needle The string to look for
* @param needle_len The length of the search string
* @return A pointer to the first occurrence of "needle" in
* "haystack". If "needle" isn't found or is NULL, or if
* "needle_len" is 0, NULL is returned.
*/
WS_DLL_PUBLIC
const guint8 *ws_memmem(const void *haystack, size_t haystack_len,
const void *needle, size_t needle_len);
/** Finds the first occurrence of string 'needle' in string 'haystack'.
* The matching is done in a case insensitive manner.
*
* @param haystack The string possibly containing the substring
* @param needle The substring to be searched
* @return A pointer into 'haystack' where 'needle' is first found.
* Otherwise it returns NULL.
*/
WS_DLL_PUBLIC
const char *ws_strcasestr(const char *haystack, const char *needle);
WS_DLL_PUBLIC
int ws_xton(char ch);