Skip to content

CryptoJS.enc.Base64url.parse bug #531

@Li13

Description

@Li13

描述

在使用CryptoJS的Base64url.parse方法时,当第二个参数传入false(表示不使用urlSafe模式),会导致后续所有Base64url.parse调用无论是否传入第二个参数,都使用非urlSafe的映射表(map),从而出现解析错误。

根本原因 :内部urlSafe和非urlSafe两种加密方式共用了同一个映射表(map),导致不同调用之间相互干扰。

复现步骤

  1. 调用 CryptoJS.enc.Base64url.parse('dGVzdA==', false)
  2. 再调用 CryptoJS.enc.Base64url.parse('dGVzdA') (正常情况下应该解析为字符串"test")
  3. 发现解析结果不正确,因为此时使用的是非urlSafe的映射表

预期行为

每次调用parse方法时,应该根据传入的第二个参数选择对应的映射表,或者每次调用都重新初始化映射表,避免调用之间相互影响。

实际行为

第一次调用传入false后,后续所有调用都使用非urlSafe的映射表,导致urlSafe格式的base64字符串解析失败。

Description

When using the CryptoJS.enc.Base64url.parse method with the second parameter set to false (indicating not to use urlSafe mode), it causes all subsequent Base64url.parse calls to use the non-urlSafe map regardless of whether the second parameter is provided, resulting in parsing errors.

Root Cause : The urlSafe and non-urlSafe encryption methods share the same internal map, leading to cross-interference between different calls.

Reproduction Steps

  1. Call CryptoJS.enc.Base64url.parse('dGVzdA==', false)
  2. Then call CryptoJS.enc.Base64url.parse('dGVzdA') (which should normally parse to the string "test")
  3. Observe that the parsing result is incorrect because the non-urlSafe map is being used

Expected Behavior

Each call to the parse method should select the corresponding map based on the second parameter passed in, or reinitialize the map for each call to avoid interference between calls.

Actual Behavior

After the first call with the false parameter, all subsequent calls use the non-urlSafe map, causing urlSafe formatted base64 strings to fail to parse correctly.

parse: function (base64Str, urlSafe) {
    if (urlSafe === undefined) {
        urlSafe = true
    }

    // Shortcuts
    var base64StrLength = base64Str.length;
    var map = urlSafe ? this._safe_map : this._map;
    // this !!!!!!!
    var reverseMap = this._reverseMap;

    if (!reverseMap) {
        reverseMap = this._reverseMap = [];
        for (var j = 0; j < map.length; j++) {
            reverseMap[map.charCodeAt(j)] = j;
        }
    }

    // Ignore padding
    var paddingChar = map.charAt(64);
    if (paddingChar) {
        var paddingIndex = base64Str.indexOf(paddingChar);
        if (paddingIndex !== -1) {
            base64StrLength = paddingIndex;
        }
    }

    // Convert
    return parseLoop(base64Str, base64StrLength, reverseMap);

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions