Merge pull request #7811 from bplu4t2f/fix-7763

Fix #7763: Fix base64 decoder edge case
This commit is contained in:
Jeroen van Rijn authored and GitHub committed 2026-10-08 10:24:58 -07:00
commit 8866bd3252
4 files changed
+154 -1

No files matched your search

+1 -1
View File
@@ -533,5 +533,5 @@ decoded_len :: proc(data: string) -> int {
}
}
return ((length * 6) >> 3) - padding
return max(0, ((length * 6) >> 3) - padding)
}
+1
View File
@@ -103,6 +103,7 @@ clang -c ..\test_issue_sysv_abi.c -o test_issue_sysv_abi_c.o || exit /b
..\..\..\odin check ..\test_issue_poly_proc_value.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "4" || exit /b
..\..\..\odin test ..\test_issue_7779.odin %COMMON% || exit /b
..\..\..\odin run ..\test_issue_7798.odin %COMMON% || exit /b
..\..\..\odin test ..\test_issue_7763.odin %COMMON% || exit /b
..\..\..\odin test ..\test_issue_disabled_proc_value.odin %COMMON% -disable-assert || exit /b
@echo off
+1
View File
@@ -272,6 +272,7 @@ $ODIN test ../test_issue_7547.odin $COMMON -debug
$ODIN test ../test_issue_7490.odin $COMMON
$ODIN test ../test_issue_7779.odin $COMMON
$ODIN run ../test_issue_7798.odin $COMMON
$ODIN test ../test_issue_7763.odin $COMMON
$ODIN test ../test_issue_disabled_proc_value.odin $COMMON -disable-assert
set +x
+151
View File
@@ -0,0 +1,151 @@
package test_issues
import "core:log"
import "core:testing"
import "core:encoding/base64"
import "core:slice"
import "core:strings"
@(test)
test_issue_7763__nothing :: proc(t: ^testing.T) {
input := ""
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__1eq :: proc(t: ^testing.T) {
input := "="
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__2eq :: proc(t: ^testing.T) {
input := "=="
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__3eq :: proc(t: ^testing.T) {
for i in 3 ..= 8 {
input := strings.repeat("=", i, context.temp_allocator)
// NOTE: Error behavior is not well-defined at this point, but it should not crash and should return an empty slice.
decoded, err := base64.decode(input)
if err != nil {
log.infof("base64 decode %q yielded: %v", input, err)
}
testing.expect(t, decoded == nil)
}
}
@(test)
test_issue_7763__Aeq :: proc(t: ^testing.T) {
input := "A="
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__QQ :: proc(t: ^testing.T) {
input := "QQ"
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, slice.equal(decoded, { 'A' }))
delete(decoded)
}
@(test)
test_issue_7763__QQ1eq :: proc(t: ^testing.T) {
input := "QQ="
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, slice.equal(decoded, { 'A' }))
delete(decoded)
}
@(test)
test_issue_7763__QQ2eq :: proc(t: ^testing.T) {
input := "QQ=="
decoded, err := base64.decode(input)
testing.expect(t, err == nil)
testing.expect(t, slice.equal(decoded, { 'A' }))
delete(decoded)
}
@(test)
test_issue_7763__QQ3eq :: proc(t: ^testing.T) {
for i in 3 ..= 8 {
// QQ====[...]
input := strings.concatenate({ "QQ", strings.repeat("=", i, context.temp_allocator) }, context.temp_allocator)
// NOTE: Error behavior is not well-defined at this point, but it should not crash, and in case it's successful, it should give 'A'.
decoded, err := base64.decode(input)
if err != nil {
log.infof("base64 decode %q yielded: %v", input, err)
testing.expect(t, decoded == nil)
} else {
testing.expect(t, decoded != nil)
delete(decoded)
}
}
}
// Strict
@(test)
test_issue_7763__strict_eq :: proc(t: ^testing.T) {
for i in 1 ..= 8 {
input := strings.repeat("=", i, context.temp_allocator)
decoded, err := base64.decode(input, options = { .Strict })
testing.expect_value(t, err, .Invalid_Padding)
testing.expect(t, decoded == nil)
}
}
@(test)
test_issue_7763__strict_Aeq :: proc(t: ^testing.T) {
input := "A="
decoded, err := base64.decode(input, options = { .Strict })
testing.expect_value(t, err, .Invalid_Padding)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__strict_QQ :: proc(t: ^testing.T) {
input := "QQ"
decoded, err := base64.decode(input, options = { .Strict })
testing.expect_value(t, err, .Invalid_Padding)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__strict_QQ1eq :: proc(t: ^testing.T) {
input := "QQ="
decoded, err := base64.decode(input, options = { .Strict })
testing.expect_value(t, err, .Invalid_Padding)
testing.expect(t, decoded == nil)
}
@(test)
test_issue_7763__strict_QQ2eq :: proc(t: ^testing.T) {
input := "QQ=="
decoded, err := base64.decode(input, options = { .Strict })
testing.expect(t, err == nil)
testing.expect(t, slice.equal(decoded, { 'A' }))
delete(decoded)
}
@(test)
test_issue_7763__strict_QQ3eq :: proc(t: ^testing.T) {
for i in 3 ..= 8 {
input := strings.concatenate({ "QQ", strings.repeat("=", i, context.temp_allocator) }, context.temp_allocator)
decoded, err := base64.decode(input, options = { .Strict })
testing.expect_value(t, err, .Invalid_Padding)
testing.expect(t, decoded == nil)
}
}