Add missing uint64 read and write helpers

This commit is contained in:
Richard Hughes 2021-03-05 17:19:17 +00:00
parent c8d0afe33d
commit f2849d24cc
3 changed files with 180 additions and 0 deletions

View File

@ -853,6 +853,33 @@ fu_common_write_uint32 (guint8 *buf, guint32 val_native, FuEndianType endian)
memcpy (buf, &val_hw, sizeof(val_hw)); memcpy (buf, &val_hw, sizeof(val_hw));
} }
/**
* fu_common_write_uint64:
* @buf: A writable buffer
* @val_native: a value in host byte-order
* @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
*
* Writes a value to a buffer using a specified endian.
*
* Since: 1.5.8
**/
void
fu_common_write_uint64 (guint8 *buf, guint64 val_native, FuEndianType endian)
{
guint64 val_hw;
switch (endian) {
case G_BIG_ENDIAN:
val_hw = GUINT64_TO_BE(val_native);
break;
case G_LITTLE_ENDIAN:
val_hw = GUINT64_TO_LE(val_native);
break;
default:
g_assert_not_reached ();
}
memcpy (buf, &val_hw, sizeof(val_hw));
}
/** /**
* fu_common_read_uint16: * fu_common_read_uint16:
* @buf: A readable buffer * @buf: A readable buffer
@ -911,6 +938,35 @@ fu_common_read_uint32 (const guint8 *buf, FuEndianType endian)
return val_native; return val_native;
} }
/**
* fu_common_read_uint64:
* @buf: A readable buffer
* @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
*
* Read a value from a buffer using a specified endian.
*
* Returns: a value in host byte-order
*
* Since: 1.5.8
**/
guint64
fu_common_read_uint64 (const guint8 *buf, FuEndianType endian)
{
guint64 val_hw, val_native;
memcpy (&val_hw, buf, sizeof(val_hw));
switch (endian) {
case G_BIG_ENDIAN:
val_native = GUINT64_FROM_BE(val_hw);
break;
case G_LITTLE_ENDIAN:
val_native = GUINT64_FROM_LE(val_hw);
break;
default:
g_assert_not_reached ();
}
return val_native;
}
/** /**
* fu_common_strtoull: * fu_common_strtoull:
* @str: A string, e.g. "0x1234" * @str: A string, e.g. "0x1234"
@ -2179,6 +2235,47 @@ fu_common_read_uint32_safe (const guint8 *buf,
return TRUE; return TRUE;
} }
/**
* fu_common_read_uint64_safe:
* @buf: source buffer
* @bufsz: maximum size of @buf, typically `sizeof(buf)`
* @offset: offset in bytes into @buf to copy from
* @value: (out) (allow-none): the parsed value
* @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
* @error: A #GError or %NULL
*
* Read a value from a buffer using a specified endian in a safe way.
*
* You don't need to use this function in "obviously correct" cases, nor should
* you use it when performance is a concern. Only us it when you're not sure if
* malicious data from a device or firmware could cause memory corruption.
*
* Return value: %TRUE if @value was set, %FALSE otherwise
*
* Since: 1.5.8
**/
gboolean
fu_common_read_uint64_safe (const guint8 *buf,
gsize bufsz,
gsize offset,
guint64 *value,
FuEndianType endian,
GError **error)
{
guint8 dst[8] = { 0x0 };
g_return_val_if_fail (buf != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!fu_memcpy_safe (dst, sizeof(dst), 0x0, /* dst */
buf, bufsz, offset, /* src */
sizeof(dst), error))
return FALSE;
if (value != NULL)
*value = fu_common_read_uint64 (dst, endian);
return TRUE;
}
/** /**
* fu_common_write_uint8_safe: * fu_common_write_uint8_safe:
* @buf: source buffer * @buf: source buffer
@ -2288,6 +2385,44 @@ fu_common_write_uint32_safe (guint8 *buf,
sizeof(tmp), error); sizeof(tmp), error);
} }
/**
* fu_common_write_uint64_safe:
* @buf: source buffer
* @bufsz: maximum size of @buf, typically `sizeof(buf)`
* @offset: offset in bytes into @buf to write to
* @value: the value to write
* @endian: A #FuEndianType, e.g. %G_LITTLE_ENDIAN
* @error: A #GError or %NULL
*
* Write a value to a buffer using a specified endian in a safe way.
*
* You don't need to use this function in "obviously correct" cases, nor should
* you use it when performance is a concern. Only us it when you're not sure if
* malicious data from a device or firmware could cause memory corruption.
*
* Return value: %TRUE if @value was written, %FALSE otherwise
*
* Since: 1.5.8
**/
gboolean
fu_common_write_uint64_safe (guint8 *buf,
gsize bufsz,
gsize offset,
guint64 value,
FuEndianType endian,
GError **error)
{
guint8 tmp[8] = { 0x0 };
g_return_val_if_fail (buf != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
fu_common_write_uint64 (tmp, value, endian);
return fu_memcpy_safe (buf, bufsz, offset, /* dst */
tmp, sizeof(tmp), 0x0, /* src */
sizeof(tmp), error);
}
/** /**
* fu_byte_array_append_uint8: * fu_byte_array_append_uint8:
* @array: A #GByteArray * @array: A #GByteArray
@ -2339,6 +2474,24 @@ fu_byte_array_append_uint32 (GByteArray *array, guint32 data, FuEndianType endia
g_byte_array_append (array, buf, sizeof(buf)); g_byte_array_append (array, buf, sizeof(buf));
} }
/**
* fu_byte_array_append_uint64:
* @array: A #GByteArray
* @data: #guint64
* @endian: #FuEndianType
*
* Adds a 64 bit integer to a byte array
*
* Since: 1.5.8
**/
void
fu_byte_array_append_uint64 (GByteArray *array, guint64 data, FuEndianType endian)
{
guint8 buf[8];
fu_common_write_uint64 (buf, data, endian);
g_byte_array_append (array, buf, sizeof(buf));
}
/** /**
* fu_byte_array_set_size: * fu_byte_array_set_size:
* @array: a #GByteArray * @array: a #GByteArray

View File

@ -224,6 +224,13 @@ gboolean fu_common_read_uint32_safe (const guint8 *buf,
FuEndianType endian, FuEndianType endian,
GError **error) GError **error)
G_GNUC_WARN_UNUSED_RESULT; G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_read_uint64_safe (const guint8 *buf,
gsize bufsz,
gsize offset,
guint64 *value,
FuEndianType endian,
GError **error)
G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_write_uint8_safe (guint8 *buf, gboolean fu_common_write_uint8_safe (guint8 *buf,
gsize bufsz, gsize bufsz,
gsize offset, gsize offset,
@ -244,6 +251,13 @@ gboolean fu_common_write_uint32_safe (guint8 *buf,
FuEndianType endian, FuEndianType endian,
GError **error) GError **error)
G_GNUC_WARN_UNUSED_RESULT; G_GNUC_WARN_UNUSED_RESULT;
gboolean fu_common_write_uint64_safe (guint8 *buf,
gsize bufsz,
gsize offset,
guint64 value,
FuEndianType endian,
GError **error)
G_GNUC_WARN_UNUSED_RESULT;
void fu_byte_array_set_size (GByteArray *array, void fu_byte_array_set_size (GByteArray *array,
guint length); guint length);
@ -255,6 +269,9 @@ void fu_byte_array_append_uint16 (GByteArray *array,
void fu_byte_array_append_uint32 (GByteArray *array, void fu_byte_array_append_uint32 (GByteArray *array,
guint32 data, guint32 data,
FuEndianType endian); FuEndianType endian);
void fu_byte_array_append_uint64 (GByteArray *array,
guint64 data,
FuEndianType endian);
void fu_common_write_uint16 (guint8 *buf, void fu_common_write_uint16 (guint8 *buf,
guint16 val_native, guint16 val_native,
@ -262,10 +279,15 @@ void fu_common_write_uint16 (guint8 *buf,
void fu_common_write_uint32 (guint8 *buf, void fu_common_write_uint32 (guint8 *buf,
guint32 val_native, guint32 val_native,
FuEndianType endian); FuEndianType endian);
void fu_common_write_uint64 (guint8 *buf,
guint64 val_native,
FuEndianType endian);
guint16 fu_common_read_uint16 (const guint8 *buf, guint16 fu_common_read_uint16 (const guint8 *buf,
FuEndianType endian); FuEndianType endian);
guint32 fu_common_read_uint32 (const guint8 *buf, guint32 fu_common_read_uint32 (const guint8 *buf,
FuEndianType endian); FuEndianType endian);
guint64 fu_common_read_uint64 (const guint8 *buf,
FuEndianType endian);
guint fu_common_string_replace (GString *string, guint fu_common_string_replace (GString *string,
const gchar *search, const gchar *search,

View File

@ -775,8 +775,13 @@ LIBFWUPDPLUGIN_1.5.8 {
global: global:
fu_bluez_device_notify_start; fu_bluez_device_notify_start;
fu_bluez_device_notify_stop; fu_bluez_device_notify_stop;
fu_byte_array_append_uint64;
fu_common_read_uint64;
fu_common_read_uint64_safe;
fu_common_write_uint16_safe; fu_common_write_uint16_safe;
fu_common_write_uint32_safe; fu_common_write_uint32_safe;
fu_common_write_uint64;
fu_common_write_uint64_safe;
fu_common_write_uint8_safe; fu_common_write_uint8_safe;
fu_device_get_backend_id; fu_device_get_backend_id;
fu_device_get_battery_level; fu_device_get_battery_level;