#include "c_Hex.h" #include #include #include #include /* -------------------------------------------------------------------------------------------------------------- */ /* */ #define BYTE_AT(A, I) (*(((unsigned char*)(A))+(I))) /* ================================================================================ */ void c_Hex_DumpBin(const void* data, c_size_t size, int line_size){ for(c_size_t i=0; i=0; d--){ putchar((b & (1<= ' ' && ((unsigned char*)data)[i] <= '~') { ascii[i % 16] = ((unsigned char*)data)[i]; } else { ascii[i % 16] = '.'; } if ((i+1) % 8 == 0 || i+1 == size) { dump(" "); if ((i+1) % 16 == 0) { dump("| %s \n", ascii); } else if (i+1 == size) { ascii[(i+1) % 16] = '\0'; if ((i+1) % 16 <= 8) { dump(" "); } for (j = (i+1) % 16; j < 16; ++j) { dump(" "); } dump("| %s \n", ascii); } } } } /* ================================================================================ */ // // static const uint8_t LOOKUP_TABLE_LOWER[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; // static const uint8_t LOOKUP_TABLE_UPPER[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}; // // char* c_Hex_BinToHex(const uint8_t *data // , c_size_t data_size // , const bool isUpperCase // , const c_ByteOrder_t byteOrder) // { // // assert(data); // assert(data_size > 0); // // c_size_t i; // const c_size_t buffer_size = (data_size << 1 ) + 1; // // char* buffer = C_ALLOC(buffer_size); // if (!buffer) { // return NULL; // } // assert(buffer); // // const uint8_t* lookup = isUpperCase?LOOKUP_TABLE_UPPER:LOOKUP_TABLE_LOWER; // // for(i =0; i> 4) & 0x0F]; // buffer[(i<<1) + 1] = (char)lookup[(data[index] & 0x0F)]; // } // // buffer[buffer_size] = '\0'; // // return buffer; // } /* ================================================================================ */ #if 0 static const unsigned char TBL[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 58, 59, 60, 61, 62, 63, 64, 10, 11, 12, 13, 14, 15, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 10, 11, 12, 13, 14, 15 }; static const unsigned char *LOOKUP = TBL - 48; uint8_t* c_Hex_HexToBin(const char* hex, const c_size_t hex_size, c_size_t* returnSize){ uint8_t b1, b2; c_size_t bin_size = hex_size >> 1; uint8_t* buffer = C_ALLOC(bin_size); if (!buffer) { return NULL; } assert(buffer); const char* in = hex; const char* end = in + hex_size; while(in < end){ b1 = LOOKUP[(uint8_t)*(in++)]; b2 = LOOKUP[(uint8_t)*(in++)]; *(buffer) = ( b1 << 4) | b2; buffer++; } if (returnSize) { *returnSize = bin_size; } return buffer - bin_size; } void c_Hex_Free(void* ptr) { C_FREE(ptr); } #endif /** * @brief 内部私有:将单个十六进制字符转换为合规的 4 位无符号半字节(Nibble) * * 🌟【高吞吐无损硬容错】:完美兼容大小写,一旦遭遇非法杂质字符立刻返回 -1 触发拦截 */ C_STATIC_FORCE_INLINE int c_Hex_CharToNibble(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; // 捕获到非法十六进制元素 } /** * @brief 工业级二进制安全:十六进制文本字符串逆向解析还原为真实二进制字节流 * * @param hex_str 待解析的标准十六进制文本字符串(以 '\0' 截止,如 "4A00FE") * @param out_bin 由外部声明传入、用于承接导出的二进制字节流物理缓冲区首地址 * @param bin_max_cap 外部缓冲区 out_bin 的最大物理插槽配额上限限制(防缓冲区溢出踩踏) * @param out_size 🌟【物理边界锁】:成功转化后,通过此二级指针强行传出实际生成的【真实字节总个数 (N)】 */ c_err_t c_Hex_HexToBin(const char* hex_str, void* out_bin, c_size_t bin_max_cap, c_size_t* out_size) { // 1. 前置毒入参非法强拦截 if (!hex_str || !out_bin || !out_size || bin_max_cap == 0) { return C_ERR_PARAM; } c_size_t hex_len = strlen(hex_str); if (hex_len == 0) { *out_size = 0; return C_ERR_EMPTY; } // 🌟【硬核格式契约 1】:十六进制字符串每 2 个可显示字符拼接成 1 个完整字节。 // 如果总字符长度为奇数,说明控制流发生非对称残缺,属于恶意或不合规输入,立刻原地熔断! if ((hex_len & 1) != 0) { *out_size = 0; return C_ERR_PARAM; } // 计算出本次还原所期望开辟生成的精确二进制字节体量 c_size_t required_bin_size = hex_len >> 1; // 🌟【硬核格式契约 2】:前置上界高位拦截。 // 若外部承接缓冲区的物理最大上限 capacity 根本吃不下这批数据,强行抛出越界异常,物理粉碎堆溢出! if (required_bin_size > bin_max_cap) { *out_size = 0; return C_ERR_OUTOFBOUND; } unsigned char* bin_buf = (unsigned char*)out_bin; // 2. 启动双字高频滑窗位移状态机 for (c_size_t i = 0; i < required_bin_size; i++) { // 每轮循环,密集抓取 2 个相邻的十六进制可显示字符 char high_char = hex_str[i << 1]; char low_char = hex_str[(i << 1) + 1]; int high_nibble = c_Hex_CharToNibble(high_char); int low_nibble = c_Hex_CharToNibble(low_char); // 🌟【硬核格式契约 3】:如果沿途解包走查发现夹杂了任何非十六进制可打印杂质字符(如 G), // 判定该报文已被严重污染,立刻启动自毁灭机制清空已生成数据,严肃报错退出! if (high_nibble < 0 || low_nibble < 0) { memset(out_bin, 0, bin_max_cap); // 洗净泄露 *out_size = 0; return C_ERR_PARAM; } // 3. 高低位半字节(Nibble)按位执行物理高位填补拼接:(High << 4) | Low bin_buf[i] = (unsigned char)((high_nibble << 4) | low_nibble); } // 4. 锁定物理绝对边界传出,不依附任何文本 \0 截断 *out_size = required_bin_size; return C_ERR_OK; } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ /** * @brief 工业级二进制安全:二进制字节流正向解析还原为标准十六进制文本字符串 * * @param in_bin 待转化的二进制字节流物理缓冲区首地址(二进制安全,支持 \0 内置流) * @param bin_size 二进制字节流的绝对有效物理字节总大小 (N) * @param uppercase 控制开关:true 导出为大写十六进制字符串(如 "4A00FE");false 导出为小写(如 "4a00fe") * @param out_hex_str 由外部声明传入、用于承接导出的十六进制可写文本缓冲区起始地址 * @param hex_max_cap 外部文本缓冲区的最大物理插槽配额上限限制(防缓冲区溢出踩踏) */ c_err_t c_Hex_BinToHex(const void* in_bin, c_size_t bin_size, bool uppercase, char* out_hex_str, c_size_t hex_max_cap) { // 1. 前置毒入参非法强拦截 if (!in_bin || !out_hex_str || hex_max_cap == 0) { return C_ERR_PARAM; } if (bin_size == 0) { if (hex_max_cap > 0) { out_hex_str[0] = '\0'; } return C_ERR_EMPTY; } // 🌟【硬核算术加固】:前置逆向除法与乘位溢出防御审计 // 计算出本次还原所期望生成的文本矩阵绝对字节体量:N * 2 + 1 (含末尾 \0 终止符) if (((c_size_t)-1 - 1) / 2 < bin_size) { return C_ERR_NOMEM; } c_size_t required_hex_size = (bin_size << 1) + 1; // 🌟【硬核格式契约】:前置上界高位拦截。 // 若外部承接缓冲区的物理最大上限 capacity 根本吃不下这批数据,强行抛出越界异常,物理粉碎堆溢出! if (required_hex_size > hex_max_cap) { return C_ERR_OUTOFBOUND; } const unsigned char* bin_buf = (const unsigned char*)in_bin; // 弹性选择十六进制多态高速查找字母表 const char* hex_digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; // 2. 启动单向滑窗转换状态机 for (c_size_t i = 0; i < bin_size; i++) { unsigned char byte_val = bin_buf[i]; // 分离高、低位半字节(Nibble)按位定位至字母表矩阵 out_hex_str[i << 1] = hex_digits[(byte_val >> 4) & 0x0F]; // 提取高 4 位 out_hex_str[(i << 1) + 1] = hex_digits[byte_val & 0x0F]; // 提取低 4 位 } // 3. 完美格式化合拢:在尾端强制安全截断注入标准 C 风格 '\0' 终止符 out_hex_str[bin_size << 1] = '\0'; return C_ERR_OK; }