aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/gsm/gsm48_ie.h6
-rw-r--r--src/gsm/gsm48_ie.c28
-rw-r--r--src/gsm/libosmogsm.map1
3 files changed, 33 insertions, 2 deletions
diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h
index f7cc24ea..71050df5 100644
--- a/include/osmocom/gsm/gsm48_ie.h
+++ b/include/osmocom/gsm/gsm48_ie.h
@@ -13,7 +13,11 @@
/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
int gsm48_decode_bcd_number(char *output, int output_len,
- const uint8_t *bcd_lv, int h_len);
+ const uint8_t *bcd_lv, int h_len)
+ OSMO_DEPRECATED("Use gsm48_decode_bcd_number2() for improved bounds checking");
+int gsm48_decode_bcd_number2(char *output, size_t output_len,
+ const uint8_t *bcd_lv, size_t input_len,
+ size_t h_len);
/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
diff --git a/src/gsm/gsm48_ie.c b/src/gsm/gsm48_ie.c
index ffe3ebae..049f5dc6 100644
--- a/src/gsm/gsm48_ie.c
+++ b/src/gsm/gsm48_ie.c
@@ -46,7 +46,7 @@ static const char bcd_num_digits[] = {
'8', '9', '*', '#', 'a', 'b', 'c', '\0'
};
-/*! decode a 'called/calling/connect party BCD number' as in 10.5.4.7
+/*! Like gsm48_decode_bcd_number2() but with less airtight bounds checking.
* \param[out] Caller-provided output buffer
* \param[in] bcd_lv Length-Value portion of to-be-decoded IE
* \param[in] h_len Length of an optional heder between L and V portion
@@ -76,6 +76,32 @@ int gsm48_decode_bcd_number(char *output, int output_len,
return 0;
}
+/*! Decode a 'called/calling/connect party BCD number' as in 10.5.4.7.
+ * \param[out] output Caller-provided output buffer.
+ * \param[in] output_len sizeof(output).
+ * \param[in] bcd_lv Length-Value part of to-be-decoded IE.
+ * \param[in] input_len Size of the buffer to read the IE from.
+ * \param[in] h_len Length of an optional header between L and V parts.
+ * \return 0 in case of success, negative on error. Errors checked: no or too little input data, no or too little
+ * output buffer size, IE length exceeds input data size, decoded number exceeds size of the output buffer. The output
+ * is guaranteed to be nul terminated iff output_len > 0.
+ */
+int gsm48_decode_bcd_number2(char *output, size_t output_len,
+ const uint8_t *bcd_lv, size_t input_len,
+ size_t h_len)
+{
+ uint8_t len;
+ if (output_len < 1)
+ return -ENOSPC;
+ *output = '\0';
+ if (input_len < 1)
+ return -EIO;
+ len = bcd_lv[0];
+ if (input_len < len)
+ return -EIO;
+ return gsm48_decode_bcd_number(output, output_len, bcd_lv, h_len);
+}
+
/*! convert a single ASCII character to call-control BCD */
static int asc_to_bcd(const char asc)
{
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 5bb189f7..9c5123e7 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -312,6 +312,7 @@ gsm48_construct_ra;
gsm48_encode_ra;
gsm48_hdr_gmm_cipherable;
gsm48_decode_bcd_number;
+gsm48_decode_bcd_number2;
gsm48_decode_bearer_cap;
gsm48_decode_called;
gsm48_decode_callerid;