Re: [Maple Bug 修正] - str_decode 造成 SIGSEGV

看板Maple (BBS架站)作者時間22年前 (2002/05/14 04:17), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串2/3 (看更多)
※ 引述《chunhan.bbs@bbs.cs.nthu.edu.tw (Hook Club)》之銘言: : Maple 系列 Bug - str_decode : 可能影響之系統: Maple v2.36, Maple v3.02, Maple v3.10, 以及其延伸版本 : 像是 Sob, Ptt, 以及 WD 等. : 目前已經確定影響之系統: Maple v3.10 (自己的站) : WD 全版本 (幫別人管的站) : ----------------------------------------------------------------------------- : 問題背景: str_decode.c (/home/bbs/src/lib) : str_decode 是將一個原本以 QP/BASE64 編碼的字串內容,將其解碼後, : 存放回原字串的一個函式。如果傳入了大於緩衝區數目的字元進入,那麼函式 : 運作期間,將導致 SIGSEGV (segmentation violation),程式終止運行. : 有問題的程式區段如下: (以 Maple 為例子) 好吧, 既然有人提了 這是我 2,3 年前改的版本, 有些部分是剛才改回跟 maple 相容 (未測試), 另外修正了一些 maple 原本 decode 上的小錯誤 供您做參考, 希望有幫助 /*-------------------------------------------------------*/ /* lib/str_decode.c ( NTHU CS MapleBBS Ver 3.00 ) */ /*-------------------------------------------------------*/ /* target : included C for QP/BASE64 decoding */ /* create : 95/03/29 */ /* update : 97/03/29 */ /*-------------------------------------------------------*/ #include <string.h> /* ----------------------------------------------------- */ /* QP code : "0123456789ABCDEF" */ /* ----------------------------------------------------- */ static int qp_code(x) int x; { if (x >= '0' && x <= '9') /* 10 */ return x - '0'; if (x >= 'A' && x <= 'F') /* 5 */ return x - 'A' + 10; /* For QP code: * Uppercase letters must be used; lowercase letters are not allowed. * include lower case for robustness purpose */ if (x >= 'a' && x <= 'f') /* 5 */ return x - 'a' + 10; /* shouldn't happen, it should be guarded by isxdigit() */ return 0; } /* ------------------------------------------------------------------ */ /* BASE64 : */ /* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" */ /* ------------------------------------------------------------------ */ static int b64_code(x) int x; { if (x >= 'A' && x <= 'Z') /* 26 */ return x - 'A'; if (x >= 'a' && x <= 'z') /* 26 */ return x - 'a' + 26; if (x >= '0' && x <= '9') /* 10 */ return x - '0' + 52; if (x == '+') return 62; if (x == '/') return 63; return -1; } /* ----------------------------------------------------- */ /* judge & decode QP / BASE64 */ /* ----------------------------------------------------- */ static inline int is_return(c) unsigned char c; { return (c == '\r' || c == '\n'); } static inline int is_space(c) unsigned char c; { return (c == ' ' || c == '\t' || is_return(c)); } int b64_decode(src, dst, n) unsigned char *src; unsigned char *dst; unsigned int n; { unsigned char *t; int x, bits, pattern; bits = pattern = 0; t = dst; while (n-- > 0) { x = b64_code(*src++); /* ignore everything not in the base64 eg. (=,\n...) */ if (x < 0) continue; pattern = (pattern << 6) | x; bits += 6; /* 1 code gains 6 bits */ if (bits >= 8) { /* enough to form a byte */ bits -= 8; *t++ = (pattern >> bits) & 0xff; } } return (t - dst); } int qp_decode(src, dst, n) unsigned char *src; unsigned char *dst; unsigned int n; { unsigned char *t; int x, y; t = dst; while (n-- > 0) { x = *src++; if (x == '=') { if (n < 2) { *t++ = '='; if (n == 1 && !is_return(x = *src)) *t++ = x; break; } x = *src++; if (is_return(x)) { --n; continue; } y = *src++; n -= 2; if ((x = qp_code(x)) < 0 || (y = qp_code(y)) < 0) { *t++ = '='; *t++ = src[-2]; *t++ = src[-1]; continue; } *t = (x << 4) + y; } else { *t = x; } ++t; } return (t - dst); } #if 0 int mmdecode(src, encode, dst) /* Thor.980901: src 和 dst 可相同, 但 src 一定以\0結束 */ unsigned char *src; unsigned char encode; /* Thor.980901: 注意, decode 出的結果不會自己加上 \0 */ unsigned char *dst; { unsigned char *t; int pattern, bits; t = dst; pattern = bits = 0; encode |= 0x20; /* Thor: to lower */ switch (encode) { case 'q': /* Thor: quoted-printable */ /* Thor.980901: 0 算是 delimiter */ while (*src) { if (*src == '=') { int x, y; x = *++src; if (x == 0) { *t++ = '='; break; } y = *++src; if (y == 0) { *t++ = '='; *t++ = x; break; } /* mail body 中的 CRLF 會被轉成單一的 \n */ if (is_return(x)) continue; if ( (x = qp_code(x)) < 0 || (y = qp_code(y)) < 0) { /* can't be decoded, just copy them */ *t++ = '='; *t++ = x; *t = y; } else { *t = (x << 4) + y; } } else if (*src == '_') { *t = ' '; } else /* Thor: *src != '=' '_' */ *t = *src; t++; src++; } return (t - dst); case 'b': /* Thor: base 64 */ while (*src) { /* Thor: pattern & bits are cleared outside */ int x; x = b64_code(*src++); /* Thor: ignore everything not in the base64,=,.. */ if (x < 0) continue; pattern = (pattern << 6) | x; bits += 6; /* Thor: 1 code gains 6 bits */ if (bits >= 8) {/* Thor: enough to form a byte */ bits -= 8; *t++ = (pattern >> bits) & 0xff; } } return (t - dst); } ASSERT(encode != 'q' && encode != 'b'); return -1; } #endif void str_decode(str) unsigned char *str; { int cc, code; unsigned char *src, *dst; unsigned char *ptr, *end; src = str; dst = str; while ((cc = *src++)) { if (is_return(cc)) while ((cc = *src++) && is_space(cc)) /* empty */; if ((cc == '=') && (*src == '?') && (ptr = strchr(src + 1, '?')) && (code = (*++ptr | 0x20)) && (*++ptr == '?') && (code == 'q' || code == 'b') && (end = strstr(++ptr, "?=")) ) { int len; len = end - ptr; for (cc = 0; cc < len; cc++) if (ptr[cc] == '_') ptr[cc] = ' '; cc = (code == 'b' ? b64_decode : qp_decode) (ptr, dst, len); if (cc >= 0) dst += cc; src = end + 2; continue; } *dst++ = cc; } *dst = 0; } -- ※ Origin: 貓空行館 ◆ From: u149-12.u203-204.giga.net.tw
文章代碼(AID): #yu1zY00 (Maple)
文章代碼(AID): #yu1zY00 (Maple)