首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言 Base64 解碼長字符串截斷:緩衝區大小不足與填充處理缺陷修正

     編輯:程式設計綜合問答

問題現象

短字符串 Base64 解碼正常,長字符串(數百字符)解碼後數據長度僅 124 字節,明顯截斷。

代碼缺陷分析

  1. 輸出緩衝區未檢查大小:調用者傳入的 bindata 空間不足,導致寫入越界或截斷
  2. 填充字符 '=' 處理邏輯脆弱:循環中 break 直接跳出,未處理剩餘數據
  3. 3. 查表法效率低:每字符遍歷 64 字符表,O(n×64) 複雜度

健壯解碼實現

#include 
#include 

static const char b64_table[256] = {
    ['A']=0,  ['B']=1,  ['C']=2,  ['D']=3,  ['E']=4,  ['F']=5,  ['G']=6,  ['H']=7,
    ['I']=8,  ['J']=9,  ['K']=10, ['L']=11, ['M']=12, ['N']=13, ['O']=14, ['P']=15,
    ['Q']=16, ['R']=17, ['S']=18, ['T']=19, ['U']=20, ['V']=21, ['W']=22, ['X']=23,
    ['Y']=24, ['Z']=25, ['a']=26, ['b']=27, ['c']=28, ['d']=29, ['e']=30, ['f']=31,
    ['g']=32, ['h']=33, ['i']=34, ['j']=35, ['k']=36, ['l']=37, ['m']=38, ['n']=39,
    ['o']=40, ['p']=41, ['q']=42, ['r']=43, ['s']=44, ['t']=45, ['u']=46, ['v']=47,
    ['w']=48, ['x']=49, ['y']=50, ['z']=51, ['0']=52, ['1']=53, ['2']=54, ['3']=55,
    ['4']=56, ['5']=57, ['6']=58, ['7']=59, ['8']=60, ['9']=61, ['+']=62, ['/']=63,
    ['=']=0  // 填充字符映射為 0
};

int base64_decode(const char *input, unsigned char **output) {
    if (!input) return -1;
    size_t len = strlen(input);
    if (len % 4 != 0) return -2; // 長度必須是 4 的倍數
    
    size_t out_len = len / 4 * 3;
    // 處理填充
    if (input[len-1] == '=') out_len--;
    if (input[len-2] == '=') out_len--;
    
    unsigned char *out = malloc(out_len + 1);
    if (!out) return -3;
    
    for (size_t i = 0, j = 0; i < len; i += 4, j += 3) {
        uint32_t sextet[4];
        for (int k = 0; k < 4; k++) {
            unsigned char c = input[i+k];
            if (c > 127 || b64_table[c] == 0 && c != '=') { free(out); return -4; }
            sextet[k] = b64_table[c];
        }
        out[j]   = (sextet[0] << 2) | (sextet[1] >> 4);
        if (i+2 < len && input[i+2] != '=') out[j+1] = (sextet[1] << 4) | (sextet[2] >> 2);
        if (i+3 < len && input[i+3] != '=') out[j+2] = (sextet[2] << 6) | sextet[3];
    }
    out[out_len] = '\0';
    *output = out;
    return out_len;
}

關鍵改進點

  • 查表優化:256 字節查表數組 O(1) 解碼,替代循環遍歷
  • 動態分配輸出:根據輸入長度精確計算輸出空間,調用者負責 free
  • 嚴格填充處理:按 RFC 4648 標準解析 '=' 位置,正確計算輸出長度
  • 輸入校驗:檢查非法字符、長度合法性

調用示例

unsigned char *decoded;
int len = base64_decode(long_base64_string, &decoded);
if (len > 0) {
    // 使用 decoded[0..len-1]
    free(decoded);
}

Base64 解碼核心:4字符→3字節,填充減少輸出生成。生產環境建議用 OpenSSL EVP_DecodeBlock 或成熟庫(libb64, Apache Commons Codec)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved