libmm-glib,common-helpers: make hexstr2bin() return a GError

This util method checks whether the input string is a valid hex
string, so make sure we return a GError on failure.
This commit is contained in:
Aleksander Morgado
2020-11-22 17:01:19 +01:00
parent dbdf67e9f7
commit 657cabcfce
11 changed files with 90 additions and 153 deletions

View File

@@ -1687,10 +1687,12 @@ mm_utils_hex2byte (const gchar *hex)
} }
gchar * gchar *
mm_utils_hexstr2bin (const gchar *hex, gsize *out_len) mm_utils_hexstr2bin (const gchar *hex,
gsize *out_len,
GError **error)
{ {
const gchar *ipos = hex; const gchar *ipos = hex;
gchar *buf = NULL; g_autofree gchar *buf = NULL;
gsize i; gsize i;
gint a; gint a;
gchar *opos; gchar *opos;
@@ -1699,20 +1701,26 @@ mm_utils_hexstr2bin (const gchar *hex, gsize *out_len)
len = strlen (hex); len = strlen (hex);
/* Length must be a multiple of 2 */ /* Length must be a multiple of 2 */
g_return_val_if_fail ((len % 2) == 0, NULL); if ((len % 2) != 0) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"Hex conversion failed: invalid input length");
return NULL;
}
opos = buf = g_malloc0 ((len / 2) + 1); opos = buf = g_malloc0 ((len / 2) + 1);
for (i = 0; i < len; i += 2) { for (i = 0; i < len; i += 2) {
a = mm_utils_hex2byte (ipos); a = mm_utils_hex2byte (ipos);
if (a < 0) { if (a < 0) {
g_free (buf); g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"Hex byte conversion from '%c%c' failed",
ipos[0], ipos[1]);
return NULL; return NULL;
} }
*opos++ = a; *opos++ = a;
ipos += 2; ipos += 2;
} }
*out_len = len / 2; *out_len = len / 2;
return buf; return g_steal_pointer (&buf);
} }
/* End from hostap */ /* End from hostap */

View File

@@ -181,7 +181,7 @@ gchar *mm_get_string_unquoted_from_match_info (GMatchInfo *match_info,
const gchar *mm_sms_delivery_state_get_string_extended (guint delivery_state); const gchar *mm_sms_delivery_state_get_string_extended (guint delivery_state);
gint mm_utils_hex2byte (const gchar *hex); gint mm_utils_hex2byte (const gchar *hex);
gchar *mm_utils_hexstr2bin (const gchar *hex, gsize *out_len); gchar *mm_utils_hexstr2bin (const gchar *hex, gsize *out_len, GError **error);
gchar *mm_utils_bin2hexstr (const guint8 *bin, gsize len); gchar *mm_utils_bin2hexstr (const guint8 *bin, gsize len);
gboolean mm_utils_ishexstr (const gchar *hex); gboolean mm_utils_ishexstr (const gchar *hex);

View File

@@ -155,9 +155,9 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
0, NULL); 0, NULL);
g_assert (regex); g_assert (regex);
if (!g_regex_match_full (regex, pco_info, strlen (pco_info), 0, 0, &match_info, error)) {
if (!g_regex_match_full (regex, pco_info, strlen (pco_info), 0, 0, &match_info, error))
return NULL; return NULL;
}
num_matches = g_match_info_get_match_count (match_info); num_matches = g_match_info_get_match_count (match_info);
if (num_matches != 5) { if (num_matches != 5) {
@@ -170,22 +170,18 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
} }
while (g_match_info_matches (match_info)) { while (g_match_info_matches (match_info)) {
guint pco_cid; guint pco_cid;
gchar *pco_id; g_autofree gchar *pco_id = NULL;
gchar *pco_payload; g_autofree gchar *pco_payload = NULL;
gsize pco_payload_len; g_autofree gchar *pco_payload_bytes = NULL;
gchar *pco_payload_bytes = NULL; gsize pco_payload_bytes_len;
gsize pco_payload_bytes_len; guint8 pco_prefix[6];
guint8 pco_prefix[6];
GByteArray *pco_raw; GByteArray *pco_raw;
gsize pco_raw_len; gsize pco_raw_len;
if (!mm_get_uint_from_match_info (match_info, 1, &pco_cid)) { if (!mm_get_uint_from_match_info (match_info, 1, &pco_cid)) {
g_set_error (error, g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
MM_CORE_ERROR, "Couldn't parse CID from PCO info: '%s'", pco_info);
MM_CORE_ERROR_FAILED,
"Couldn't parse CID from PCO info: '%s'",
pco_info);
break; break;
} }
@@ -197,42 +193,26 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
pco_id = mm_get_string_unquoted_from_match_info (match_info, 3); pco_id = mm_get_string_unquoted_from_match_info (match_info, 3);
if (!pco_id) { if (!pco_id) {
g_set_error (error, g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't parse PCO ID from PCO info: '%s'", pco_info);
"Couldn't parse PCO ID from PCO info: '%s'",
pco_info);
break; break;
} }
if (g_strcmp0 (pco_id, "FF00")) { if (g_strcmp0 (pco_id, "FF00")) {
g_free (pco_id);
g_match_info_next (match_info, error); g_match_info_next (match_info, error);
continue; continue;
} }
g_free (pco_id);
pco_payload = mm_get_string_unquoted_from_match_info (match_info, 4); pco_payload = mm_get_string_unquoted_from_match_info (match_info, 4);
if (!pco_payload) { if (!pco_payload) {
g_set_error (error, g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
MM_CORE_ERROR, "Couldn't parse PCO payload from PCO info: '%s'", pco_info);
MM_CORE_ERROR_FAILED,
"Couldn't parse PCO payload from PCO info: '%s'",
pco_info);
break; break;
} }
pco_payload_len = strlen (pco_payload); pco_payload_bytes = mm_utils_hexstr2bin (pco_payload, &pco_payload_bytes_len, error);
if (pco_payload_len % 2 == 0)
pco_payload_bytes = mm_utils_hexstr2bin (pco_payload, &pco_payload_bytes_len);
g_free (pco_payload);
if (!pco_payload_bytes) { if (!pco_payload_bytes) {
g_set_error (error, g_prefix_error (error, "Invalid PCO payload from PCO info '%s': ", pco_info);
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Invalid PCO payload from PCO info: '%s'",
pco_info);
break; break;
} }
@@ -267,13 +247,11 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
pco_raw = g_byte_array_sized_new (pco_raw_len); pco_raw = g_byte_array_sized_new (pco_raw_len);
g_byte_array_append (pco_raw, pco_prefix, sizeof (pco_prefix)); g_byte_array_append (pco_raw, pco_prefix, sizeof (pco_prefix));
g_byte_array_append (pco_raw, (guint8 *)pco_payload_bytes, pco_payload_bytes_len); g_byte_array_append (pco_raw, (guint8 *)pco_payload_bytes, pco_payload_bytes_len);
g_free (pco_payload_bytes);
pco = mm_pco_new (); pco = mm_pco_new ();
mm_pco_set_session_id (pco, pco_cid); mm_pco_set_session_id (pco, pco_cid);
mm_pco_set_complete (pco, TRUE); mm_pco_set_complete (pco, TRUE);
mm_pco_set_data (pco, pco_raw->data, pco_raw->len); mm_pco_set_data (pco, pco_raw->data, pco_raw->len);
g_byte_array_unref (pco_raw);
break; break;
} }

View File

@@ -2330,21 +2330,20 @@ decode (MMIfaceModem3gppUssd *self,
const gchar *reply, const gchar *reply,
GError **error) GError **error)
{ {
gchar *bin, *utf8; g_autofree gchar *bin = NULL;
guint8 *unpacked; g_autofree guint8 *unpacked = NULL;
gsize bin_len; gsize bin_len = 0;
guint32 unpacked_len; guint32 unpacked_len;
bin = mm_utils_hexstr2bin (reply, &bin_len, error);
if (!bin)
return NULL;
bin = mm_utils_hexstr2bin (reply, &bin_len);
unpacked = mm_charset_gsm_unpack ((guint8*) bin, (bin_len * 8) / 7, 0, &unpacked_len); unpacked = mm_charset_gsm_unpack ((guint8*) bin, (bin_len * 8) / 7, 0, &unpacked_len);
/* if the last character in a 7-byte block is padding, then drop it */ /* if the last character in a 7-byte block is padding, then drop it */
if ((bin_len % 7 == 0) && (unpacked[unpacked_len - 1] == 0x0d)) if ((bin_len % 7 == 0) && (unpacked[unpacked_len - 1] == 0x0d))
unpacked_len--; unpacked_len--;
utf8 = (char*) mm_charset_gsm_unpacked_to_utf8 (unpacked, unpacked_len); return (gchar*) mm_charset_gsm_unpacked_to_utf8 (unpacked, unpacked_len);
g_free (bin);
g_free (unpacked);
return utf8;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@@ -188,7 +188,7 @@ match_info_to_ip4_addr (GMatchInfo *match_info,
else else
g_assert_not_reached (); g_assert_not_reached ();
bin = mm_utils_hexstr2bin (buf, &bin_len); bin = mm_utils_hexstr2bin (buf, &bin_len, NULL);
if (!bin || bin_len != 4) if (!bin || bin_len != 4)
goto done; goto done;

View File

@@ -1291,9 +1291,9 @@ static guint
parse_mnc_length (const gchar *response, parse_mnc_length (const gchar *response,
GError **error) GError **error)
{ {
guint sw1 = 0; guint sw1 = 0;
guint sw2 = 0; guint sw2 = 0;
gchar *hex = 0; g_autofree gchar *hex = NULL;
if (!mm_3gpp_parse_crsm_response (response, if (!mm_3gpp_parse_crsm_response (response,
&sw1, &sw1,
@@ -1306,47 +1306,34 @@ parse_mnc_length (const gchar *response,
(sw1 == 0x91) || (sw1 == 0x91) ||
(sw1 == 0x92) || (sw1 == 0x92) ||
(sw1 == 0x9f)) { (sw1 == 0x9f)) {
gsize buflen = 0; gsize buflen = 0;
guint32 mnc_len; guint32 mnc_len;
gchar *bin; g_autofree gchar *bin = NULL;
/* Convert hex string to binary */ /* Convert hex string to binary */
bin = mm_utils_hexstr2bin (hex, &buflen); bin = mm_utils_hexstr2bin (hex, &buflen, error);
if (!bin || buflen < 4) { if (!bin) {
g_set_error (error, g_prefix_error (error, "SIM returned malformed response '%s': ", hex);
MM_CORE_ERROR, return 0;
MM_CORE_ERROR_FAILED, }
"SIM returned malformed response '%s'", if (buflen < 4) {
hex); g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
g_free (bin); "SIM returned malformed response '%s': too short", hex);
g_free (hex);
return 0; return 0;
} }
g_free (hex);
/* MNC length is byte 4 of this SIM file */ /* MNC length is byte 4 of this SIM file */
mnc_len = bin[3] & 0xFF; mnc_len = bin[3] & 0xFF;
if (mnc_len == 2 || mnc_len == 3) { if (mnc_len == 2 || mnc_len == 3)
g_free (bin);
return mnc_len; return mnc_len;
}
g_set_error (error, g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
MM_CORE_ERROR, "SIM returned invalid MNC length %d (should be either 2 or 3)", mnc_len);
MM_CORE_ERROR_FAILED,
"SIM returned invalid MNC length %d (should be either 2 or 3)",
mnc_len);
g_free (bin);
return 0; return 0;
} }
g_free (hex); g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
g_set_error (error, "SIM failed to handle CRSM request (sw1 %d sw2 %d)", sw1, sw2);
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SIM failed to handle CRSM request (sw1 %d sw2 %d)",
sw1, sw2);
return 0; return 0;
} }
@@ -1410,9 +1397,9 @@ static gchar *
parse_spn (const gchar *response, parse_spn (const gchar *response,
GError **error) GError **error)
{ {
guint sw1 = 0; guint sw1 = 0;
guint sw2 = 0; guint sw2 = 0;
gchar *hex = 0; g_autofree gchar *hex = NULL;
if (!mm_3gpp_parse_crsm_response (response, if (!mm_3gpp_parse_crsm_response (response,
&sw1, &sw1,
@@ -1425,40 +1412,26 @@ parse_spn (const gchar *response,
(sw1 == 0x91) || (sw1 == 0x91) ||
(sw1 == 0x92) || (sw1 == 0x92) ||
(sw1 == 0x9f)) { (sw1 == 0x9f)) {
gsize buflen = 0; gsize buflen = 0;
gchar *bin; g_autofree gchar *bin = NULL;
gchar *utf8;
/* Convert hex string to binary */ /* Convert hex string to binary */
bin = mm_utils_hexstr2bin (hex, &buflen); bin = mm_utils_hexstr2bin (hex, &buflen, error);
if (!bin) { if (!bin) {
g_set_error (error, g_prefix_error (error, "SIM returned malformed response '%s': ", hex);
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SIM returned malformed response '%s'",
hex);
g_free (hex);
return NULL; return NULL;
} }
g_free (hex);
/* Remove the FF filler at the end */ /* Remove the FF filler at the end */
while (buflen > 1 && bin[buflen - 1] == (char)0xff) while (buflen > 1 && bin[buflen - 1] == (char)0xff)
buflen--; buflen--;
/* First byte is metadata; remainder is GSM-7 unpacked into octets; convert to UTF8 */ /* First byte is metadata; remainder is GSM-7 unpacked into octets; convert to UTF8 */
utf8 = (gchar *)mm_charset_gsm_unpacked_to_utf8 ((guint8 *)bin + 1, buflen - 1); return (gchar *)mm_charset_gsm_unpacked_to_utf8 ((guint8 *)bin + 1, buflen - 1);
g_free (bin);
return utf8;
} }
g_free (hex); g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
g_set_error (error, "SIM failed to handle CRSM request (sw1 %d sw2 %d)", sw1, sw2);
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"SIM failed to handle CRSM request (sw1 %d sw2 %d)",
sw1, sw2);
return NULL; return NULL;
} }

View File

@@ -169,7 +169,7 @@ mm_modem_charset_hex_to_utf8 (const gchar *src,
iconv_from = charset_iconv_from (charset); iconv_from = charset_iconv_from (charset);
g_return_val_if_fail (iconv_from != NULL, FALSE); g_return_val_if_fail (iconv_from != NULL, FALSE);
unconverted = mm_utils_hexstr2bin (src, &unconverted_len); unconverted = mm_utils_hexstr2bin (src, &unconverted_len, NULL);
if (!unconverted) if (!unconverted)
return NULL; return NULL;

View File

@@ -1811,25 +1811,19 @@ mm_firmware_unique_id_to_qmi_unique_id (const gchar *unique_id,
/* The length will be exactly EXPECTED_QMI_UNIQUE_ID_LENGTH*2 if given in HEX */ /* The length will be exactly EXPECTED_QMI_UNIQUE_ID_LENGTH*2 if given in HEX */
if (len == (2 * EXPECTED_QMI_UNIQUE_ID_LENGTH)) { if (len == (2 * EXPECTED_QMI_UNIQUE_ID_LENGTH)) {
guint8 *tmp; g_autofree guint8 *tmp = NULL;
gsize tmp_len; gsize tmp_len;
guint i;
for (i = 0; i < len; i++) {
if (!g_ascii_isxdigit (unique_id[i])) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Unexpected character found in unique id (not HEX): %c", unique_id[i]);
return NULL;
}
}
tmp_len = 0; tmp_len = 0;
tmp = (guint8 *) mm_utils_hexstr2bin (unique_id, &tmp_len); tmp = (guint8 *) mm_utils_hexstr2bin (unique_id, &tmp_len, error);
if (!tmp) {
g_prefix_error (error, "Unexpected character found in unique id: ");
return NULL;
}
g_assert (tmp_len == EXPECTED_QMI_UNIQUE_ID_LENGTH); g_assert (tmp_len == EXPECTED_QMI_UNIQUE_ID_LENGTH);
qmi_unique_id = g_array_sized_new (FALSE, FALSE, sizeof (guint8), tmp_len); qmi_unique_id = g_array_sized_new (FALSE, FALSE, sizeof (guint8), tmp_len);
g_array_insert_vals (qmi_unique_id, 0, tmp, tmp_len); g_array_insert_vals (qmi_unique_id, 0, tmp, tmp_len);
g_free (tmp);
return qmi_unique_id; return qmi_unique_id;
} }

View File

@@ -4291,10 +4291,9 @@ mm_3gpp_parse_emergency_numbers (const char *raw, GError **error)
return NULL; return NULL;
} }
bin = (guint8 *) mm_utils_hexstr2bin (raw, &binlen); bin = (guint8 *) mm_utils_hexstr2bin (raw, &binlen, error);
if (!bin) { if (!bin) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, g_prefix_error (error, "invalid raw emergency numbers list contents: ");
"invalid raw emergency numbers list contents: %s", raw);
return NULL; return NULL;
} }

View File

@@ -339,24 +339,17 @@ mm_sms_part_3gpp_new_from_pdu (guint index,
gpointer log_object, gpointer log_object,
GError **error) GError **error)
{ {
gsize pdu_len; g_autofree guint8 *pdu = NULL;
guint8 *pdu; gsize pdu_len;
MMSmsPart *part;
/* Convert PDU from hex to binary */ /* Convert PDU from hex to binary */
pdu = (guint8 *) mm_utils_hexstr2bin (hexpdu, &pdu_len); pdu = (guint8 *) mm_utils_hexstr2bin (hexpdu, &pdu_len, error);
if (!pdu) { if (!pdu) {
g_set_error_literal (error, g_prefix_error (error, "Couldn't convert 3GPP PDU from hex to binary: ");
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Couldn't convert 3GPP PDU from hex to binary");
return NULL; return NULL;
} }
part = mm_sms_part_3gpp_new_from_binary_pdu (index, pdu, pdu_len, log_object, error); return mm_sms_part_3gpp_new_from_binary_pdu (index, pdu, pdu_len, log_object, error);
g_free (pdu);
return part;
} }
MMSmsPart * MMSmsPart *

View File

@@ -317,24 +317,17 @@ mm_sms_part_cdma_new_from_pdu (guint index,
gpointer log_object, gpointer log_object,
GError **error) GError **error)
{ {
gsize pdu_len; g_autofree guint8 *pdu = NULL;
guint8 *pdu; gsize pdu_len;
MMSmsPart *part;
/* Convert PDU from hex to binary */ /* Convert PDU from hex to binary */
pdu = (guint8 *) mm_utils_hexstr2bin (hexpdu, &pdu_len); pdu = (guint8 *) mm_utils_hexstr2bin (hexpdu, &pdu_len, error);
if (!pdu) { if (!pdu) {
g_set_error_literal (error, g_prefix_error (error, "Couldn't convert CDMA PDU from hex to binary: ");
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Couldn't convert CDMA PDU from hex to binary");
return NULL; return NULL;
} }
part = mm_sms_part_cdma_new_from_binary_pdu (index, pdu, pdu_len, log_object, error); return mm_sms_part_cdma_new_from_binary_pdu (index, pdu, pdu_len, log_object, error);
g_free (pdu);
return part;
} }
struct Parameter { struct Parameter {