Re: [Maple Bug 修正] - str_decode 造成 SIGSEGV
※ 引述《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
討論串 (同標題文章)
Maple 近期熱門文章
PTT數位生活區 即時熱門文章