From 8212fc6a7d9cfd6c5e71f522863c3e3420262360 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 1 Apr 2019 14:34:37 +0200 Subject: add gsm48_decode_bcd_number2() from osmo-msc gsm48_decode_bcd_number() is unable to provide proper bounds validation of input and output data, hence osmo-msc's vlr.c introduced a static decode_bcd_number_safe() a long time ago. Move to libosmocore. I need to use the same function to decode an MSISDN during inter-MSC Handover, instead of making it public in osmo-msc, rather deprecate the unsafe function and provide a safer version for all callers. Mark the old one deprecated. Change-Id: Idb6ae6e2f3bea11ad420dae14d021ac36d99e921 --- src/gsm/gsm48_ie.c | 28 +++++++++++++++++++++++++++- src/gsm/libosmogsm.map | 1 + 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'src/gsm') 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; -- cgit v1.2.3