7位PDU解析中'@'字符被解析为0x00的问题排查
SMS消息解析器中'@'被解析为0x00的问题与解决
问题背景
开发SMS消息解析器时,其余功能正常,但部分场景下'@'字符被解析为0x00而非0x40。多段代码测试结果一致,但在线PDU解析器可正确解析报文。
所用代码
uint8_t uArr[] = {0xF0, 0x7B, 0x2F, 0x26, 0x9B, 0xD1, 0x6A, 0xB6, 0x78, 0x94, 0x05, 0x9F, 0xF7, 0x00, 0xA6, 0xDD, 0x2F, 0xD4, 0x7A, 0xE9, 0x76}; uint8_t uOut_Arr[0x19]; uint8_t i,b; uint8_t length = 0x19; b = 0; for (i = 0; i < length; i++) { int byte_idx = i * 7 / 8; int bit_idx = i * 7 % 8; uint16_t ch = uArr[byte_idx] >> bit_idx; if (bit_idx > 0) { ch |= (uint16_t)uArr[byte_idx + 1] << (8 - bit_idx); } uOut_Arr[b++] = (uint8_t)(ch & 0x7F); } printf(uOut_Arr);
问题详情
转换后得到的序列:
F0 7B 2F 26 9B D1 6A B6 78 94 05 9F F7 00 A6 DD 2F D4 7A E9 76
预期结果应为pw=123456qQ,ps=@&;;?!-/:;,但'@'对应数组索引13的位置出现空值。完整PDU报文为:
07919781340310F1040B919751390289F700006250401160512118F07B2F269BD16AB67894059FF700A6DD2FD47AE976
实际发送内容确为pw=123456qQ,ps=@&;;?!-/:;,在线解析器解析结果正确。
问题原因
- 解码逻辑错误:代码的7位字符拼接逻辑不符合GSM 03.38规范。GSM 7位编码是将每个字符的bit0到bit6依次存入比特流,再按字节打包(字节的bit0对应比特流起始位)。你的移位拼接方式未正确提取每个字符的对应比特位,导致'@'的高位比特错位或丢失。
- 数组越界风险:设置的
length=0x19(25)超出了uArr的实际长度(21个元素),当循环到i>=20时会访问数组外的内存,引发未定义行为。
解决方法
使用逐位提取的方式解码,严格遵循GSM 7位编码的比特顺序。修正后的代码如下:
uint8_t uArr[] = {0xF0, 0x7B, 0x2F, 0x26, 0x9B, 0xD1, 0x6A, 0xB6, 0x78, 0x94, 0x05, 0x9F, 0xF7, 0x00, 0xA6, 0xDD, 0x2F, 0xD4, 0x7A, 0xE9, 0x76}; uint8_t uOut_Arr[25]; uint8_t b = 0; size_t total_bits = sizeof(uArr) * 8; size_t out_len = total_bits / 7; if (total_bits % 7 != 0) { out_len++; } for (size_t i = 0; i < out_len; i++) { uint8_t ch = 0; for (int j = 0; j < 7; j++) { size_t bit_pos = i * 7 + j; size_t byte_idx = bit_pos / 8; size_t bit_idx = bit_pos % 8; if (byte_idx >= sizeof(uArr)) { break; } if (uArr[byte_idx] & (1 << bit_idx)) { ch |= (1 << j); } } uOut_Arr[b++] = ch; } uOut_Arr[b] = '\0'; // 添加字符串结束符,避免printf输出乱码 printf("%s\n", uOut_Arr);
在线解析器能正确解析的原因
在线解析器采用了符合GSM规范的标准解码逻辑,能正确处理7位编码的比特打包顺序,同时会自动规避数组越界等问题,因此可以得到正确结果。
内容的提问来源于stack exchange,提问作者Mishakol
相关产品推荐
相关产品推荐

