diff --git a/src/smsutil.c b/src/smsutil.c index 8c084d42..450a1d38 100644 --- a/src/smsutil.c +++ b/src/smsutil.c @@ -1756,7 +1756,7 @@ gboolean sms_udh_iter_init_from_cbs(const struct cbs *cbs, return FALSE; hdr = cbs->ud; - max_ud_len = 82; + max_ud_len = cbs->udlen; /* Must have at least one information-element if udhi is true */ if (hdr[0] < 2) @@ -3862,8 +3862,8 @@ gboolean cbs_dcs_decode(guint8 dcs, gboolean *udhi, enum sms_class *cls, gboolean cbs_decode(const unsigned char *pdu, int len, struct cbs *out) { - /* CBS is always a fixed length of 88 bytes */ - if (len != 88) + /* CBS is (almost) always a fixed length of 88 bytes */ + if (len < 6 || len > 88) return FALSE; out->gs = (enum cbs_geo_scope) ((pdu[0] >> 6) & 0x03); @@ -3874,6 +3874,10 @@ gboolean cbs_decode(const unsigned char *pdu, int len, struct cbs *out) out->max_pages = pdu[5] & 0xf; out->page = (pdu[5] >> 4) & 0xf; + /* Allow the last fragment to be truncated */ + if (len != 88 && out->max_pages != out->page) + return FALSE; + /* * If a mobile receives the code 0000 in either the first field or * the second field then it shall treat the CBS message exactly the @@ -3885,7 +3889,10 @@ gboolean cbs_decode(const unsigned char *pdu, int len, struct cbs *out) out->page = 1; } - memcpy(out->ud, pdu + 6, 82); + out->udlen = (guint8)(len - 6); + memcpy(out->ud, pdu + 6, out->udlen); + if (out->udlen < 82) + memset(out->ud + out->udlen, 0, 82 - out->udlen); return TRUE; } @@ -4078,7 +4085,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang) if (iso639) bufsize -= 3; } else { - bufsize += 82; + bufsize += cbs->udlen; if (iso639) bufsize -= 2; @@ -4095,7 +4102,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang) if (sms_udh_iter_init_from_cbs(cbs, &iter)) taken = sms_udh_iter_get_udh_length(&iter) + 1; - unpack_7bit_own_buf(cbs->ud + taken, 82 - taken, + unpack_7bit_own_buf(cbs->ud + taken, cbs->udlen - taken, taken, false, 2, NULL, 0, (unsigned char *)iso639_lang); @@ -4128,7 +4135,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang) max_chars = sms_text_capacity_gsm(CBS_MAX_GSM_CHARS, taken); - unpack_7bit_own_buf(ud + taken, 82 - taken, + unpack_7bit_own_buf(ud + taken, cbs->udlen - taken, taken, false, max_chars, &written, 0, unpacked); @@ -4162,7 +4169,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang) * the check here since the specification isn't clear */ } else { - int num_ucs2_chars = (82 - taken) >> 1; + int num_ucs2_chars = (cbs->udlen - taken) >> 1; int i = taken; int max_offset = taken + num_ucs2_chars * 2; diff --git a/src/smsutil.h b/src/smsutil.h index 0adba51c..01487de4 100644 --- a/src/smsutil.h +++ b/src/smsutil.h @@ -408,6 +408,7 @@ struct cbs { guint8 dcs; /* 8 bits */ guint8 max_pages; /* 4 bits */ guint8 page; /* 4 bits */ + guint8 udlen; guint8 ud[82]; };