summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Jannotti <jannotti@gmail.com>2022-05-21 23:38:15 -0400
committerGitHub <noreply@github.com>2022-05-21 23:38:15 -0400
commit4a922c405f6847854e569a2624c97b7549078091 (patch)
treece698fe9f47c94e085b38a3f4c9e19cd6afe0f60
parentd06c9aa33d7cfdf55174dcc76b9465407fb05de9 (diff)
base64_decode can decode padded or unpadded encodings (#4015)2062-on-chain-warning-scenario-3
-rw-r--r--data/transactions/logic/eval.go22
-rw-r--r--data/transactions/logic/eval_test.go24
2 files changed, 27 insertions, 19 deletions
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index e621ef38e..2a2614b94 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -4716,6 +4716,21 @@ func base64Decode(encoded []byte, encoding *base64.Encoding) ([]byte, error) {
return decoded[:n], err
}
+// base64padded returns true iff `encoded` has padding chars at the end
+func base64padded(encoded []byte) bool {
+ for i := len(encoded) - 1; i > 0; i-- {
+ switch encoded[i] {
+ case '=':
+ return true
+ case '\n', '\r':
+ /* nothing */
+ default:
+ return false
+ }
+ }
+ return false
+}
+
func opBase64Decode(cx *EvalContext) error {
last := len(cx.stack) - 1
encodingField := Base64Encoding(cx.program[cx.pc+1])
@@ -4728,8 +4743,11 @@ func opBase64Decode(cx *EvalContext) error {
if encodingField == StdEncoding {
encoding = base64.StdEncoding
}
- encoding = encoding.Strict()
- bytes, err := base64Decode(cx.stack[last].Bytes, encoding)
+ encoded := cx.stack[last].Bytes
+ if !base64padded(encoded) {
+ encoding = encoding.WithPadding(base64.NoPadding)
+ }
+ bytes, err := base64Decode(encoded, encoding.Strict())
if err != nil {
return err
}
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 04b3741eb..9e54e7b29 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -4649,12 +4649,12 @@ By Herman Melville`, "",
{"cGFk=", "StdEncoding", "pad", "input byte 4"},
{"cGFk==", "StdEncoding", "pad", "input byte 4"},
{"cGFk===", "StdEncoding", "pad", "input byte 4"},
- // Ensures that even correct padding is illegal if not needed
+ // Ensures that extra padding, even if 0%4
{"cGFk====", "StdEncoding", "pad", "input byte 4"},
- // Test that padding must be present to make len = 0 mod 4.
+ // Test that padding must be correct or absent
{"bm9wYWQ=", "StdEncoding", "nopad", ""},
- {"bm9wYWQ", "StdEncoding", "nopad", "illegal"},
+ {"bm9wYWQ", "StdEncoding", "nopad", ""},
{"bm9wYWQ==", "StdEncoding", "nopad", "illegal"},
{"YWJjMTIzIT8kKiYoKSctPUB+", "StdEncoding", "abc123!?$*&()'-=@~", ""},
@@ -4690,15 +4690,15 @@ By Herman Melville`, "",
{"\rS\r\nQ=\n=\r\r\n", "StdEncoding", "I", ""},
{"\rS\r\nQ=\n=\r\r\n", "URLEncoding", "I", ""},
- // Padding necessary? - Yes it is! And exactly the expected place and amount.
+ // If padding is there, it must be correct, but if absent, that's fine.
{"SQ==", "StdEncoding", "I", ""},
{"SQ==", "URLEncoding", "I", ""},
{"S=Q=", "StdEncoding", "", "byte 1"},
{"S=Q=", "URLEncoding", "", "byte 1"},
{"=SQ=", "StdEncoding", "", "byte 0"},
{"=SQ=", "URLEncoding", "", "byte 0"},
- {"SQ", "StdEncoding", "", "byte 0"},
- {"SQ", "URLEncoding", "", "byte 0"},
+ {"SQ", "StdEncoding", "I", ""},
+ {"SQ", "URLEncoding", "I", ""},
{"SQ=", "StdEncoding", "", "byte 3"},
{"SQ=", "URLEncoding", "", "byte 3"},
{"SQ===", "StdEncoding", "", "byte 4"},
@@ -4721,17 +4721,6 @@ By Herman Melville`, "",
if LogicVersion < fidoVersion {
testProg(t, source, AssemblerMaxVersion, Expect{0, "unknown opcode..."})
} else {
- // sanity check - test the helper function first:
- encoding := base64.URLEncoding
- if tc.alph == "StdEncoding" {
- encoding = base64.StdEncoding
- }
- encoding = encoding.Strict()
- decoded, err := base64Decode([]byte(tc.encoded), encoding)
- require.NoError(t, err)
- require.Equal(t, string(decoded), tc.decoded)
-
- // now check eval:
testAccepts(t, source, fidoVersion)
}
} else {
@@ -4739,6 +4728,7 @@ By Herman Melville`, "",
testProg(t, source, AssemblerMaxVersion, Expect{0, "unknown opcode..."})
} else {
err := testPanics(t, source, fidoVersion)
+ require.Error(t, err)
require.Contains(t, err.Error(), tc.error)
}
}