mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-05 10:27:11 +00:00
Add fu_memmem_safe() with fallback code for win32
This commit is contained in:
parent
b92fe4a760
commit
52fd89f9ab
@ -2328,6 +2328,82 @@ fu_memcpy_safe(guint8 *dst,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_memmem_safe:
|
||||
* @haystack: destination buffer
|
||||
* @haystack_sz: maximum size of @haystack, typically `sizeof(haystack)`
|
||||
* @needle: source buffer
|
||||
* @needle_sz: maximum size of @haystack, typically `sizeof(needle)`
|
||||
* @offset: (out) (nullable): offset in bytes @needle has been found in @haystack
|
||||
* @error: (nullable): optional return location for an error
|
||||
*
|
||||
* Finds a block of memory in another block of memory in a safe way.
|
||||
*
|
||||
* Returns: %TRUE if the needle was found in the haystack, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.7.4
|
||||
**/
|
||||
gboolean
|
||||
fu_memmem_safe(const guint8 *haystack,
|
||||
gsize haystack_sz,
|
||||
const guint8 *needle,
|
||||
gsize needle_sz,
|
||||
gsize *offset,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef HAVE_MEMMEM
|
||||
const guint8 *tmp;
|
||||
#endif
|
||||
g_return_val_if_fail(haystack != NULL, FALSE);
|
||||
g_return_val_if_fail(needle != NULL, FALSE);
|
||||
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
||||
|
||||
/* nothing to find */
|
||||
if (needle_sz == 0) {
|
||||
if (offset != NULL)
|
||||
*offset = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* impossible */
|
||||
if (needle_sz > haystack_sz) {
|
||||
g_set_error(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_FOUND,
|
||||
"needle of 0x%02x bytes is larger than haystack of 0x%02x bytes",
|
||||
(guint)needle_sz,
|
||||
(guint)haystack_sz);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MEMMEM
|
||||
/* trust glibc to do a binary or linear search as appropriate */
|
||||
tmp = memmem(haystack, haystack_sz, needle, needle_sz);
|
||||
if (tmp != NULL) {
|
||||
if (offset != NULL)
|
||||
*offset = tmp - haystack;
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
for (gsize i = 0; i < haystack_sz - needle_sz; i++) {
|
||||
if (memcmp(haystack + i, needle, needle_sz) == 0) {
|
||||
if (offset != NULL)
|
||||
*offset = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* not found */
|
||||
g_set_error(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_FOUND,
|
||||
"needle of 0x%02x bytes was not found in haystack of 0x%02x bytes",
|
||||
(guint)needle_sz,
|
||||
(guint)haystack_sz);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_memdup_safe:
|
||||
* @src: source buffer
|
||||
|
@ -263,6 +263,13 @@ fu_memcpy_safe(guint8 *dst,
|
||||
gsize n,
|
||||
GError **error) G_GNUC_WARN_UNUSED_RESULT;
|
||||
gboolean
|
||||
fu_memmem_safe(const guint8 *haystack,
|
||||
gsize haystack_sz,
|
||||
const guint8 *needle,
|
||||
gsize needle_sz,
|
||||
gsize *offset,
|
||||
GError **error) G_GNUC_WARN_UNUSED_RESULT;
|
||||
gboolean
|
||||
fu_common_read_uint8_safe(const guint8 *buf,
|
||||
gsize bufsz,
|
||||
gsize offset,
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "fu-common.h"
|
||||
#include "fu-fmap-firmware.h"
|
||||
|
||||
@ -24,31 +22,6 @@
|
||||
|
||||
G_DEFINE_TYPE(FuFmapFirmware, fu_fmap_firmware, FU_TYPE_FIRMWARE)
|
||||
|
||||
static gboolean
|
||||
fu_fmap_firmware_find_offset(FuFmapFirmware *self, const guint8 *buf, gsize bufsz, GError **error)
|
||||
{
|
||||
#ifdef HAVE_MEMMEM
|
||||
const guint8 *tmp;
|
||||
|
||||
g_return_val_if_fail(buf != NULL, FALSE);
|
||||
|
||||
/* trust glibc to do a binary or linear search as appropriate */
|
||||
tmp = memmem(buf, bufsz, FMAP_SIGNATURE, 8);
|
||||
if (tmp == NULL) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"fmap header not found");
|
||||
return FALSE;
|
||||
}
|
||||
fu_firmware_set_offset(FU_FIRMWARE(self), tmp - buf);
|
||||
return TRUE;
|
||||
#else
|
||||
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "memmem() not available");
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_fmap_firmware_parse(FuFirmware *firmware,
|
||||
GBytes *fw,
|
||||
@ -57,7 +30,6 @@ fu_fmap_firmware_parse(FuFirmware *firmware,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
FuFmapFirmware *self = FU_FMAP_FIRMWARE(firmware);
|
||||
FuFmapFirmwareClass *klass_firmware = FU_FMAP_FIRMWARE_GET_CLASS(firmware);
|
||||
gsize bufsz;
|
||||
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
||||
@ -75,8 +47,9 @@ fu_fmap_firmware_parse(FuFirmware *firmware,
|
||||
|
||||
/* only search for the fmap signature if not fuzzing */
|
||||
if ((flags & FWUPD_INSTALL_FLAG_NO_SEARCH) == 0) {
|
||||
if (!fu_fmap_firmware_find_offset(self, buf, bufsz, error))
|
||||
if (!fu_memmem_safe(buf, bufsz, (const guint8 *)FMAP_SIGNATURE, 8, &offset, error))
|
||||
return FALSE;
|
||||
fu_firmware_set_offset(firmware, offset);
|
||||
}
|
||||
|
||||
/* load header */
|
||||
@ -85,7 +58,7 @@ fu_fmap_firmware_parse(FuFirmware *firmware,
|
||||
0x0, /* dst */
|
||||
buf,
|
||||
bufsz,
|
||||
fu_firmware_get_offset(firmware), /* src */
|
||||
offset, /* src */
|
||||
sizeof(fmap),
|
||||
error))
|
||||
return FALSE;
|
||||
@ -108,7 +81,7 @@ fu_fmap_firmware_parse(FuFirmware *firmware,
|
||||
GUINT16_FROM_LE(fmap.nareas));
|
||||
return FALSE;
|
||||
}
|
||||
offset = fu_firmware_get_offset(firmware) + sizeof(fmap);
|
||||
offset += sizeof(fmap);
|
||||
|
||||
for (gsize i = 0; i < GUINT16_FROM_LE(fmap.nareas); i++) {
|
||||
FuFmapArea area;
|
||||
|
@ -479,6 +479,30 @@ _strnsplit_nop_cb(GString *token, guint token_idx, gpointer user_data, GError **
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_common_memmem_func(void)
|
||||
{
|
||||
const guint8 haystack[] = {'H', 'A', 'Y', 'S'};
|
||||
const guint8 needle[] = {'A', 'Y'};
|
||||
gboolean ret;
|
||||
gsize offset = 0;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
ret = fu_memmem_safe(haystack, sizeof(haystack), needle, sizeof(needle), &offset, &error);
|
||||
g_assert_no_error(error);
|
||||
g_assert_true(ret);
|
||||
g_assert_cmpint(offset, ==, 0x1);
|
||||
|
||||
ret = fu_memmem_safe(haystack + 2,
|
||||
sizeof(haystack) - 2,
|
||||
needle,
|
||||
sizeof(needle),
|
||||
&offset,
|
||||
&error);
|
||||
g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND);
|
||||
g_assert_false(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_common_strnsplit_func(void)
|
||||
{
|
||||
@ -3789,6 +3813,7 @@ main(int argc, char **argv)
|
||||
g_setenv("FWUPD_LOCALSTATEDIR", "/tmp/fwupd-self-test/var", TRUE);
|
||||
|
||||
g_test_add_func("/fwupd/common{strnsplit}", fu_common_strnsplit_func);
|
||||
g_test_add_func("/fwupd/common{memmem}", fu_common_memmem_func);
|
||||
g_test_add_func("/fwupd/progress", fu_progress_func);
|
||||
g_test_add_func("/fwupd/progress{child}", fu_progress_child_func);
|
||||
g_test_add_func("/fwupd/progress{parent-1-step}", fu_progress_parent_one_step_proxy_func);
|
||||
|
@ -977,3 +977,9 @@ LIBFWUPDPLUGIN_1.7.3 {
|
||||
fu_common_sum8_bytes;
|
||||
local: *;
|
||||
} LIBFWUPDPLUGIN_1.7.2;
|
||||
|
||||
LIBFWUPDPLUGIN_1.7.4 {
|
||||
global:
|
||||
fu_memmem_safe;
|
||||
local: *;
|
||||
} LIBFWUPDPLUGIN_1.7.3;
|
||||
|
Loading…
Reference in New Issue
Block a user