牛骨文教育服务平台(让学习变的简单)
博文笔记

php扩展开发笔记(7) 错误使用 php_base64_decode 导致内存溢出

创建时间:2015-06-16 投稿人: 浏览次数:2333

在开发解密函数的时候,因为调用了 php_base64_decode 内核自带的扩展函数,导致内存溢出,而且是在某些情况下溢出。经排查是由于忽略了 php_base64_decode 的参数,先来看看这个函数的原型

PHPAPI unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_length) /* {{{ */
{
    return php_base64_decode_ex(str, length, ret_length, 0);
}
/* }}} */

PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, int *ret_length, zend_bool strict) /* {{{ */
{
    const unsigned char *current = str;
    int ch, i = 0, j = 0, k;
    /* this sucks for threaded environments */
    unsigned char *result;

    result = (unsigned char *)safe_emalloc(length, 1, 1);

    /* run through the whole string, converting as we go */
    while ((ch = *current++) != "" && length-- > 0) {
        if (ch == base64_pad) {
            if (*current != "=" && ((i % 4) == 1 || (strict && length > 0))) {
                if ((i % 4) != 1) {
                    while (isspace(*(++current))) {
                        continue;
                    }
                    if (*current == "") {
                        continue;
                    }
                }
                efree(result);
                return NULL;
            }
            continue;
        }

        ch = base64_reverse_table[ch];
        if ((!strict && ch < 0) || ch == -1) { /* a space or some other separator character, we simply skip over */
            continue;
        } else if (ch == -2) {
            efree(result);
            return NULL;
        }

        switch(i % 4) {
        case 0:
            result[j] = ch << 2;
            break;
        case 1:
            result[j++] |= ch >> 4;
            result[j] = (ch & 0x0f) << 4;
            break;
        case 2:
            result[j++] |= ch >>2;
            result[j] = (ch & 0x03) << 6;
            break;
        case 3:
            result[j++] |= ch;
            break;
        }
        i++;
    }

    k = j;
    /* mop things up if we ended on a boundary */
    if (ch == base64_pad) {
        switch(i % 4) {
        case 1:
            efree(result);
            return NULL;
        case 2:
            k++;
        case 3:
            result[k] = 0;
        }
    }
    if(ret_length) {
        *ret_length = j;
    }
    result[j] = "";
    return result;
}
/* }}} */

这个函数返回一个 char * 类型,并且给返回值计算了长度 ret_length,下面是调用代码

char *str_decode = (char *) php_base64_decode((unsigned char *) str_to_decode, strlen(str_to_decode), &str_decode_len);

因为解密的时候,需要计算 str_decode 这个变量的长度,我使用了 strlen(str_decode) ,这样带来的结果就是 strlen(str_decode) 和 ret_length 这个值在有些情况下是不想等的,具体在哪些情况下不想等,大家可以看上面贴出来的代码。

所以,就是因为这个 strlen(str_decode) 使用不当,导致了内存溢出。

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。