This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
suraev at alumni.ntnu.no suraev at alumni.ntnu.noFrom: Max <msuraev at sysmocom.de> Refactor and simplify gsm 7 bit decoder. Remove useless tests for legacy functions. Make tests more human-readable. Replace assert inside the library with returning error code. Ticket: OW#1198 Sponsored-by: On-Waves ehf --- src/gsm/gsm_utils.c | 35 +++++++++++++++++------------- tests/sms/sms_test.c | 59 ++++++++++++++++++++++++--------------------------- tests/sms/sms_test.ok | 28 +++++++++--------------- 3 files changed, 58 insertions(+), 64 deletions(-) diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index fad59bc..bcc0271 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -126,18 +126,17 @@ uint8_t gsm_get_octet_len(const uint8_t sept_len){ return octet_len; } -/* GSM 03.38 6.2.1 Character unpacking */ +/* GSM 03.38 6.2.1 Character unpacking + * returns -1 on size errors, number of characters otherwise + */ int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind) { - int i = 0; - int shift = 0; - uint8_t c7, c8; - uint8_t next_is_ext = 0; + unsigned shift = 0; + uint8_t c7, c8, next_is_ext = 0, lu, ru, maxlen = gsm_get_octet_len(septet_l); const char *text_buf_begin = text; const char *text_buf_end = text + n; - int nchars; - OSMO_ASSERT (n > 0); + if (n < 1) return -1; /* skip the user data header */ if (ud_hdr_ind) { @@ -148,12 +147,20 @@ int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_ septet_l = septet_l - shift; } + unsigned i, l, r; for (i = 0; i < septet_l && text != text_buf_end - 1; i++) { - c7 = - ((user_data[((i + shift) * 7 + 7) >> 3] << - (7 - (((i + shift) * 7 + 7) & 7))) | - (user_data[((i + shift) * 7) >> 3] >> - (((i + shift) * 7) & 7))) & 0x7f; + + l = ((i + shift) * 7 + 7) >> 3; + r = ((i + shift) * 7) >> 3; + + if (l >= maxlen) + lu = 0; // workaround to prevent getting out of bounds + else + lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7)); + + ru = user_data[r] >> (((i + shift) * 7) & 7); + + c7 = (lu | ru) & 0x7f; if (next_is_ext) { /* this is an extension character */ @@ -169,11 +176,9 @@ int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_ *(text++) = c8; } - nchars = text - text_buf_begin; - *text = '\0'; - return nchars; + return text - text_buf_begin; } int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l) diff --git a/tests/sms/sms_test.c b/tests/sms/sms_test.c index cdd4158..1927925 100644 --- a/tests/sms/sms_test.c +++ b/tests/sms/sms_test.c @@ -44,6 +44,7 @@ struct test_case { const uint16_t expected_octet_length; const uint16_t expected_septet_length; const uint8_t ud_hdr_ind; + const char * descr; }; static const char simple_text[] = "test text"; @@ -131,6 +132,7 @@ static const struct test_case test_multiple_encode[] = .expected_octet_length = sizeof(concatenated_part1_enc), .expected_septet_length = concatenated_part1_septet_length, .ud_hdr_ind = 1, + .descr = "concatenated text p1" }, { .input = (const uint8_t *) concatenated_text, @@ -138,6 +140,7 @@ static const struct test_case test_multiple_encode[] = .expected_octet_length = sizeof(concatenated_part2_enc), .expected_septet_length = concatenated_part2_septet_length, .ud_hdr_ind = 1, + .descr = "concatenated text p2" }, }; @@ -149,6 +152,7 @@ static const struct test_case test_encode[] = .expected_octet_length = sizeof(simple_enc), .expected_septet_length = simple_septet_length, .ud_hdr_ind = 0, + .descr = "simple text" }, { .input = (const uint8_t *) escape_text, @@ -156,6 +160,7 @@ static const struct test_case test_encode[] = .expected_octet_length = sizeof(escape_enc), .expected_septet_length = escape_septet_length, .ud_hdr_ind = 0, + .descr = "escape text" }, { .input = (const uint8_t *) enhanced_text, @@ -163,6 +168,7 @@ static const struct test_case test_encode[] = .expected_octet_length = sizeof(enhanced_enc), .expected_septet_length = enhanced_septet_length, .ud_hdr_ind = 0, + .descr = "enhanced text" }, { .input = (const uint8_t *) enhancedV2_text, @@ -170,6 +176,7 @@ static const struct test_case test_encode[] = .expected_octet_length = sizeof(enhancedV2_enc), .expected_septet_length = enhancedV2_septet_length, .ud_hdr_ind = 0, + .descr = "enhanced text v2" }, }; @@ -181,6 +188,7 @@ static const struct test_case test_decode[] = .expected = (const uint8_t *) simple_text, .expected_septet_length = simple_septet_length, .ud_hdr_ind = 0, + .descr = "simple text" }, { .input = escape_enc, @@ -188,6 +196,7 @@ static const struct test_case test_decode[] = .expected = (const uint8_t *) escape_text, .expected_septet_length = escape_septet_length, .ud_hdr_ind = 0, + .descr = "escape text" }, { .input = enhanced_enc, @@ -195,6 +204,7 @@ static const struct test_case test_decode[] = .expected = (const uint8_t *) enhanced_text, .expected_septet_length = enhanced_septet_length, .ud_hdr_ind = 0, + .descr = "enhanced text" }, { .input = enhancedV2_enc, @@ -202,6 +212,7 @@ static const struct test_case test_decode[] = .expected = (const uint8_t *) enhancedV2_text, .expected_septet_length = enhancedV2_septet_length, .ud_hdr_ind = 0, + .descr = "enhanced text v2" }, { .input = concatenated_part1_enc, @@ -209,6 +220,7 @@ static const struct test_case test_decode[] = .expected = (const uint8_t *) splitted_text_part1, .expected_septet_length = concatenated_part1_septet_length_with_header, .ud_hdr_ind = 1, + .descr = "concatenated text p1" }, { .input = concatenated_part2_enc, @@ -216,7 +228,8 @@ static const struct test_case test_decode[] = .expected = (const uint8_t *) splitted_text_part2, .expected_septet_length = concatenated_part2_septet_length_with_header, .ud_hdr_ind = 1, - }, + .descr = "concatenated text p2" + }, }; static void test_octet_return() @@ -288,29 +301,17 @@ int main(int argc, char** argv) /* test 7-bit encoding */ for (i = 0; i < ARRAY_SIZE(test_encode); ++i) { - /* Test legacy function (return value only) */ - septet_length = gsm_7bit_encode(coded, - (const char *) test_encode[i].input); - printf("Legacy encode case %d: " - "septet length %d (expected %d)\n" - , i - , septet_length, test_encode[i].expected_septet_length - ); - OSMO_ASSERT (septet_length == test_encode[i].expected_septet_length); - - /* Test new function */ memset(coded, 0x42, sizeof(coded)); septet_length = gsm_7bit_encode_n(coded, sizeof(coded), (const char *) test_encode[i].input, &octets_written); computed_octet_length = gsm_get_octet_len(septet_length); - printf("Encode case %d: " - "Octet length %d (expected %d, computed %d), " - "septet length %d (expected %d)\n" - , i - , octets_written, test_encode[i].expected_octet_length, computed_octet_length - , septet_length, test_encode[i].expected_septet_length - ); + printf("Encode case %d (%s): " + "Octet length %d (expected %d, computed %d, test %s), " + "septet length %d (expected %d, test %s)\n", + i, test_encode[i].descr, + octets_written, test_encode[i].expected_octet_length, computed_octet_length, (test_encode[i].expected_octet_length == computed_octet_length) ? "OK" : "FAIL", + septet_length, test_encode[i].expected_septet_length, (septet_length == test_encode[i].expected_septet_length) ? "OK" : "FAIL"); OSMO_ASSERT (octets_written == test_encode[i].expected_octet_length); OSMO_ASSERT (octets_written == computed_octet_length); @@ -377,22 +378,18 @@ int main(int argc, char** argv) /* test 7-bit decoding */ for (i = 0; i < ARRAY_SIZE(test_decode); ++i) { - /* Test legacy function (return value only) */ - if (!test_decode[i].ud_hdr_ind) { - nchars = gsm_7bit_decode(result, test_decode[i].input, - test_decode[i].expected_septet_length); - printf("Legacy decode case %d: " - "return value %d (expected %d)\n", - i, nchars, test_decode[i].expected_septet_length); - } - - /* Test new function */ memset(result, 0x42, sizeof(result)); +// printf("Attempting to 7 bit decode %d to %d with exp %d and ind %d\n", test_decode[i].input_length, sizeof(result), test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind); nchars = gsm_7bit_decode_n_hdr(result, sizeof(result), test_decode[i].input, test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind); - printf("Decode case %d: return value %d (expected %d)\n", i, nchars, strlen(result)); + printf("Decode case %d (%s): return value %d, expected %d, test %s\n", i, test_decode[i].descr, nchars, strlen(result), (strlen(result) == nchars) ? "OK" : "FAIL"); + + int res = strcmp(result, (const char *) test_decode[i].expected); + if(0 != res) { + printf("%d:\n%s\n%s\n", res, osmo_hexdump(result, strlen(result)), + osmo_hexdump(test_decode[i].expected, strlen(result))); + } - OSMO_ASSERT(strcmp(result, (const char *) test_decode[i].expected) == 0); OSMO_ASSERT(nchars == strlen(result)); /* check buffer limiting */ diff --git a/tests/sms/sms_test.ok b/tests/sms/sms_test.ok index fa536ea..144e602 100644 --- a/tests/sms/sms_test.ok +++ b/tests/sms/sms_test.ok @@ -1,22 +1,14 @@ SMS testing -Legacy encode case 0: septet length 9 (expected 9) -Encode case 0: Octet length 8 (expected 8, computed 8), septet length 9 (expected 9) -Legacy encode case 1: septet length 41 (expected 41) -Encode case 1: Octet length 36 (expected 36, computed 36), septet length 41 (expected 41) -Legacy encode case 2: septet length 39 (expected 39) -Encode case 2: Octet length 35 (expected 35, computed 35), septet length 39 (expected 39) -Legacy encode case 3: septet length 40 (expected 40) -Encode case 3: Octet length 35 (expected 35, computed 35), septet length 40 (expected 40) -Legacy decode case 0: return value 9 (expected 9) -Decode case 0: return value 9 (expected 9) -Legacy decode case 1: return value 41 (expected 41) -Decode case 1: return value 40 (expected 40) -Legacy decode case 2: return value 39 (expected 39) -Decode case 2: return value 31 (expected 31) -Legacy decode case 3: return value 40 (expected 40) -Decode case 3: return value 32 (expected 32) -Decode case 4: return value 153 (expected 153) -Decode case 5: return value 40 (expected 40) +Encode case 0 (simple text): Octet length 8 (expected 8, computed 8, test OK), septet length 9 (expected 9, test OK) +Encode case 1 (escape text): Octet length 36 (expected 36, computed 36, test OK), septet length 41 (expected 41, test OK) +Encode case 2 (enhanced text): Octet length 35 (expected 35, computed 35, test OK), septet length 39 (expected 39, test OK) +Encode case 3 (enhanced text v2): Octet length 35 (expected 35, computed 35, test OK), septet length 40 (expected 40, test OK) +Decode case 0 (simple text): return value 9, expected 9, test OK +Decode case 1 (escape text): return value 40, expected 40, test OK +Decode case 2 (enhanced text): return value 31, expected 31, test OK +Decode case 3 (enhanced text v2): return value 32, expected 32, test OK +Decode case 4 (concatenated text p1): return value 153, expected 153, test OK +Decode case 5 (concatenated text p2): return value 40, expected 40, test OK Encoding some tests and printing number of septets/octets SEPTETS: 8 OCTETS: 7 Done -- 2.5.0