Skip to content

Commit 9a5d5cd

Browse files
authored
Followup to opcode base64_decode (#3288)
* alphabet begone in favor of encoding * unit test various padding and whitespace scenarios * padding permutations also fail * "Slicing" --> "Manipulation" * fix the codegen fail? * Documenting padding, whitespace, other character behavior
1 parent f5bf5ec commit 9a5d5cd

File tree

12 files changed

+127
-79
lines changed

12 files changed

+127
-79
lines changed

cmd/opdoc/tmLanguage.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ func buildSyntaxHighlight() *tmLanguage {
175175
// For these, accumulate into allArithmetics,
176176
// and only add to keyword.Patterns later, when all
177177
// have been collected.
178-
case "Arithmetic", "Byte Array Slicing", "Byte Array Arithmetic",
178+
case "Arithmetic", "Byte Array Manipulation", "Byte Array Arithmetic",
179179
"Byte Array Logic", "Inner Transactions":
180180
escape := map[rune]bool{
181181
'*': true,

data/transactions/logic/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ various sizes.
165165
| `extract_uint16` | pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B+2 is larger than the array length, the program fails |
166166
| `extract_uint32` | pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B+4 is larger than the array length, the program fails |
167167
| `extract_uint64` | pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B+8 is larger than the array length, the program fails |
168-
| `base64_decode e` | decode X which was base64-encoded using _encoding alphabet_ E. Fail if X is not base64 encoded with alphabet E |
168+
| `base64_decode e` | decode X which was base64-encoded using _encoding_ E. Fail if X is not base64 encoded with encoding E |
169169

170170
These opcodes take byte-array values that are interpreted as
171171
big-endian unsigned integers. For mathematical operators, the

data/transactions/logic/README_in.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ various sizes.
9090

9191
### Byte Array Manipulation
9292

93-
@@ Byte_Array_Slicing.md @@
93+
@@ Byte_Array_Manipulation.md @@
9494

9595
These opcodes take byte-array values that are interpreted as
9696
big-endian unsigned integers. For mathematical operators, the

data/transactions/logic/TEAL_opcodes.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -856,14 +856,14 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
856856

857857
## base64_decode e
858858

859-
- Opcode: 0x5c {uint8 alphabet index}
859+
- Opcode: 0x5c {uint8 encoding index}
860860
- Pops: *... stack*, []byte
861861
- Pushes: []byte
862-
- decode X which was base64-encoded using _encoding alphabet_ E. Fail if X is not base64 encoded with alphabet E
862+
- decode X which was base64-encoded using _encoding_ E. Fail if X is not base64 encoded with encoding E
863863
- **Cost**: 25
864864
- LogicSigVersion >= 6
865865

866-
decodes X using the base64 encoding alphabet E. Specify the alphabet with an immediate arg either as URL and Filename Safe (`URLAlph`) or Standard (`StdAlph`). See <a href="https://rfc-editor.org/rfc/rfc4648.html#section-4">RFC 4648</a> (sections 4 and 5)
866+
Decodes X using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See <a href="https://rfc-editor.org/rfc/rfc4648.html#section-4">RFC 4648</a> (sections 4 and 5). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
867867

868868
## balance
869869

data/transactions/logic/assembler.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,20 +1249,20 @@ func assembleBase64Decode(ops *OpStream, spec *OpSpec, args []string) error {
12491249
return ops.errorf("%s expects one argument", spec.Name)
12501250
}
12511251

1252-
alph, ok := base64AlphabetSpecByName[args[0]]
1252+
encoding, ok := base64EncodingSpecByName[args[0]]
12531253
if !ok {
1254-
return ops.errorf("%s unknown alphabet: %#v", spec.Name, args[0])
1254+
return ops.errorf("%s unknown encoding: %#v", spec.Name, args[0])
12551255
}
1256-
if alph.version > ops.Version {
1256+
if encoding.version > ops.Version {
12571257
//nolint:errcheck // we continue to maintain typestack
1258-
ops.errorf("%s %s available in version %d. Missed #pragma version?", spec.Name, args[0], alph.version)
1258+
ops.errorf("%s %s available in version %d. Missed #pragma version?", spec.Name, args[0], encoding.version)
12591259
}
12601260

1261-
val := alph.field
1261+
val := encoding.field
12621262
ops.pending.WriteByte(spec.Opcode)
12631263
ops.pending.WriteByte(uint8(val))
1264-
ops.trace("%s (%s)", alph.field, alph.ftype)
1265-
ops.returns(alph.ftype)
1264+
ops.trace("%s (%s)", encoding.field, encoding.ftype)
1265+
ops.returns(encoding.ftype)
12661266
return nil
12671267
}
12681268

@@ -2698,10 +2698,10 @@ func disBase64Decode(dis *disassembleState, spec *OpSpec) (string, error) {
26982698
}
26992699
dis.nextpc = dis.pc + 2
27002700
b64dArg := dis.program[dis.pc+1]
2701-
if int(b64dArg) >= len(base64AlphabetNames) {
2701+
if int(b64dArg) >= len(base64EncodingNames) {
27022702
return "", fmt.Errorf("invalid base64_decode arg index %d at pc=%d", b64dArg, dis.pc)
27032703
}
2704-
return fmt.Sprintf("%s %s", spec.Name, base64AlphabetNames[b64dArg]), nil
2704+
return fmt.Sprintf("%s %s", spec.Name, base64EncodingNames[b64dArg]), nil
27052705
}
27062706

27072707
type disInfo struct {

data/transactions/logic/assembler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ itxna Logs 3
344344

345345
const v6Nonsense = v5Nonsense + `
346346
itxn_next
347-
base64_decode URLAlph
347+
base64_decode URLEncoding
348348
`
349349

350350
var nonsense = map[uint64]string{

data/transactions/logic/doc.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ var opDocByName = map[string]string{
133133
"extract_uint16": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B+2 is larger than the array length, the program fails",
134134
"extract_uint32": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B+4 is larger than the array length, the program fails",
135135
"extract_uint64": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B+8 is larger than the array length, the program fails",
136-
"base64_decode": "decode X which was base64-encoded using _encoding alphabet_ E. Fail if X is not base64 encoded with alphabet E",
136+
"base64_decode": "decode X which was base64-encoded using _encoding_ E. Fail if X is not base64 encoded with encoding E",
137137

138138
"balance": "get balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted.",
139139
"min_balance": "get minimum required balance for account A, in microalgos. Required balance is affected by [ASA](https://developer.algorand.org/docs/features/asa/#assets-overview) and [App](https://developer.algorand.org/docs/features/asc1/stateful/#minimum-balance-requirement-for-a-smart-contract) usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes.",
@@ -231,7 +231,7 @@ var opcodeImmediateNotes = map[string]string{
231231
"ecdsa_pk_decompress": "{uint8 curve index}",
232232
"ecdsa_pk_recover": "{uint8 curve index}",
233233

234-
"base64_decode": "{uint8 alphabet index}",
234+
"base64_decode": "{uint8 encoding index}",
235235
}
236236

237237
// OpImmediateNote returns a short string about immediate data which follows the op byte
@@ -286,7 +286,7 @@ var opDocExtras = map[string]string{
286286
"itxn_begin": "`itxn_begin` initializes Sender to the application address; Fee to the minimum allowable, taking into account MinTxnFee and credit from overpaying in earlier transactions; FirstValid/LastValid to the values in the top-level transaction, and all other fields to zero values.",
287287
"itxn_field": "`itxn_field` fails if X is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if X is an account or asset that does not appear in `txn.Accounts` or `txn.ForeignAssets` of the top-level transaction. (Setting addresses in asset creation are exempted from this requirement.)",
288288
"itxn_submit": "`itxn_submit` resets the current transaction so that it can not be resubmitted. A new `itxn_begin` is required to prepare another inner transaction.",
289-
"base64_decode": "decodes X using the base64 encoding alphabet E. Specify the alphabet with an immediate arg either as URL and Filename Safe (`URLAlph`) or Standard (`StdAlph`). See <a href=\"https://rfc-editor.org/rfc/rfc4648.html#section-4\">RFC 4648</a> (sections 4 and 5)",
289+
"base64_decode": "Decodes X using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See <a href=\"https://rfc-editor.org/rfc/rfc4648.html#section-4\">RFC 4648</a> (sections 4 and 5). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
290290
}
291291

292292
// OpDocExtra returns extra documentation text about an op
@@ -298,14 +298,14 @@ func OpDocExtra(opName string) string {
298298
// here is the order args opcodes are presented, so place related
299299
// opcodes consecutively, even if their opcode values are not.
300300
var OpGroups = map[string][]string{
301-
"Arithmetic": {"sha256", "keccak256", "sha512_256", "ed25519verify", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat"},
302-
"Byte Array Slicing": {"substring", "substring3", "extract", "extract3", "extract_uint16", "extract_uint32", "extract_uint64", "base64_decode"},
303-
"Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%"},
304-
"Byte Array Logic": {"b|", "b&", "b^", "b~"},
305-
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gaid", "gaids"},
306-
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "cover", "uncover", "swap", "select", "assert", "callsub", "retsub"},
307-
"State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "log"},
308-
"Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna"},
301+
"Arithmetic": {"sha256", "keccak256", "sha512_256", "ed25519verify", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat"},
302+
"Byte Array Manipulation": {"substring", "substring3", "extract", "extract3", "extract_uint16", "extract_uint32", "extract_uint64", "base64_decode"},
303+
"Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%"},
304+
"Byte Array Logic": {"b|", "b&", "b^", "b~"},
305+
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gaid", "gaids"},
306+
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "cover", "uncover", "swap", "select", "assert", "callsub", "retsub"},
307+
"State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "log"},
308+
"Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna"},
309309
}
310310

311311
// OpCost indicates the cost of an operation over the range of

data/transactions/logic/eval.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4047,15 +4047,15 @@ func base64Decode(encoded []byte, encoding *base64.Encoding) ([]byte, error) {
40474047

40484048
func opBase64Decode(cx *EvalContext) {
40494049
last := len(cx.stack) - 1
4050-
alphabetField := Base64Alphabet(cx.program[cx.pc+1])
4051-
fs, ok := base64AlphabetSpecByField[alphabetField]
4050+
encodingField := Base64Encoding(cx.program[cx.pc+1])
4051+
fs, ok := base64EncodingSpecByField[encodingField]
40524052
if !ok || fs.version > cx.version {
4053-
cx.err = fmt.Errorf("invalid base64_decode alphabet %d", alphabetField)
4053+
cx.err = fmt.Errorf("invalid base64_decode encoding %d", encodingField)
40544054
return
40554055
}
40564056

40574057
encoding := base64.URLEncoding
4058-
if alphabetField == StdAlph {
4058+
if encodingField == StdEncoding {
40594059
encoding = base64.StdEncoding
40604060
}
40614061
cx.stack[last].Bytes, cx.err = base64Decode(cx.stack[last].Bytes, encoding)

data/transactions/logic/evalStateful_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2392,7 +2392,7 @@ func TestReturnTypes(t *testing.T) {
23922392
"itxn": "itxn_begin; int pay; itxn_field TypeEnum; itxn_submit; itxn CreatedAssetID",
23932393
// This next one is a cop out. Can't use itxna Logs until we have inner appl
23942394
"itxna": "itxn_begin; int pay; itxn_field TypeEnum; itxn_submit; itxn NumLogs",
2395-
"base64_decode": `pushbytes "YWJjMTIzIT8kKiYoKSctPUB+"; base64_decode StdAlph; pushbytes "abc123!?$*&()'-=@~"; ==; pushbytes "YWJjMTIzIT8kKiYoKSctPUB-"; base64_decode URLAlph; pushbytes "abc123!?$*&()'-=@~"; ==; &&; assert`,
2395+
"base64_decode": `pushbytes "YWJjMTIzIT8kKiYoKSctPUB+"; base64_decode StdEncoding; pushbytes "abc123!?$*&()'-=@~"; ==; pushbytes "YWJjMTIzIT8kKiYoKSctPUB-"; base64_decode URLEncoding; pushbytes "abc123!?$*&()'-=@~"; ==; &&; assert`,
23962396
}
23972397

23982398
// these require special input data and tested separately

data/transactions/logic/eval_test.go

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3738,15 +3738,15 @@ func BenchmarkBase64Decode(b *testing.B) {
37383738
"keccak256",
37393739
"sha256",
37403740
"sha512_256",
3741-
"base64_decode StdAlph",
3742-
"base64_decode URLAlph",
3741+
"base64_decode StdEncoding",
3742+
"base64_decode URLEncoding",
37433743
}
37443744
benches := [][]string{}
37453745
for i, tag := range tags {
37463746
for _, op := range ops {
37473747
testName := op
37483748
encoded := stds[i]
3749-
if op == "base64_decode URLAlph" {
3749+
if op == "base64_decode URLEncoding" {
37503750
encoded = urls[i]
37513751
}
37523752
if len(op) > 0 {
@@ -4961,14 +4961,16 @@ func TestPcDetails(t *testing.T) {
49614961
var minB64DecodeVersion uint64 = 6
49624962

49634963
type b64DecodeTestCase struct {
4964-
Encoded string
4965-
IsURL bool
4966-
Decoded string
4967-
Error error
4964+
Encoded string
4965+
IsURL bool
4966+
HasExtraNLs bool
4967+
Decoded string
4968+
Error error
49684969
}
49694970

49704971
var testCases = []b64DecodeTestCase{
49714972
{"TU9CWS1ESUNLOwoKb3IsIFRIRSBXSEFMRS4KCgpCeSBIZXJtYW4gTWVsdmlsbGU=",
4973+
false,
49724974
false,
49734975
`MOBY-DICK;
49744976
@@ -4980,6 +4982,7 @@ By Herman Melville`,
49804982
},
49814983
{"TU9CWS1ESUNLOwoKb3IsIFRIRSBXSEFMRS4KCgpCeSBIZXJtYW4gTWVsdmlsbGU=",
49824984
true,
4985+
false,
49834986
`MOBY-DICK;
49844987
49854988
or, THE WHALE.
@@ -4988,10 +4991,51 @@ or, THE WHALE.
49884991
By Herman Melville`,
49894992
nil,
49904993
},
4991-
{"YWJjMTIzIT8kKiYoKSctPUB+", false, "abc123!?$*&()'-=@~", nil},
4992-
{"YWJjMTIzIT8kKiYoKSctPUB-", true, "abc123!?$*&()'-=@~", nil},
4993-
{"YWJjMTIzIT8kKiYoKSctPUB+", true, "", base64.CorruptInputError(23)},
4994-
{"YWJjMTIzIT8kKiYoKSctPUB-", false, "", base64.CorruptInputError(23)},
4994+
{"YWJjMTIzIT8kKiYoKSctPUB+", false, false, "abc123!?$*&()'-=@~", nil},
4995+
{"YWJjMTIzIT8kKiYoKSctPUB-", true, false, "abc123!?$*&()'-=@~", nil},
4996+
{"YWJjMTIzIT8kKiYoKSctPUB+", true, false, "", base64.CorruptInputError(23)},
4997+
{"YWJjMTIzIT8kKiYoKSctPUB-", false, false, "", base64.CorruptInputError(23)},
4998+
4999+
// try extra ='s and various whitespace:
5000+
{"", false, false, "", nil},
5001+
{"", true, false, "", nil},
5002+
{"=", false, true, "", base64.CorruptInputError(0)},
5003+
{"=", true, true, "", base64.CorruptInputError(0)},
5004+
{" ", false, true, "", base64.CorruptInputError(0)},
5005+
{" ", true, true, "", base64.CorruptInputError(0)},
5006+
{"\t", false, true, "", base64.CorruptInputError(0)},
5007+
{"\t", true, true, "", base64.CorruptInputError(0)},
5008+
{"\r", false, true, "", nil},
5009+
{"\r", true, true, "", nil},
5010+
{"\n", false, true, "", nil},
5011+
{"\n", true, true, "", nil},
5012+
5013+
{"YWJjMTIzIT8kKiYoKSctPUB+\n", false, true, "abc123!?$*&()'-=@~", nil},
5014+
{"YWJjMTIzIT8kKiYoKSctPUB-\n", true, true, "abc123!?$*&()'-=@~", nil},
5015+
{"YWJjMTIzIT8kK\riYoKSctPUB+\n", false, true, "abc123!?$*&()'-=@~", nil},
5016+
{"YWJjMTIzIT8kK\riYoKSctPUB-\n", true, true, "abc123!?$*&()'-=@~", nil},
5017+
{"\n\rYWJjMTIzIT8\rkKiYoKSctPUB+\n", false, true, "abc123!?$*&()'-=@~", nil},
5018+
{"\n\rYWJjMTIzIT8\rkKiYoKSctPUB-\n", true, true, "abc123!?$*&()'-=@~", nil},
5019+
5020+
// padding and extra legal whitespace
5021+
{"SQ==", false, false, "I", nil},
5022+
{"SQ==", true, false, "I", nil},
5023+
{"\rS\r\nQ=\n=\r\r\n", false, true, "I", nil},
5024+
{"\rS\r\nQ=\n=\r\r\n", true, true, "I", nil},
5025+
5026+
// Padding necessary? - Yes it is! And exactly the expected place and amount.
5027+
{"SQ==", false, false, "I", nil},
5028+
{"SQ==", true, false, "I", nil},
5029+
{"S=Q=", false, false, "", base64.CorruptInputError(1)},
5030+
{"S=Q=", true, false, "", base64.CorruptInputError(1)},
5031+
{"=SQ=", false, false, "", base64.CorruptInputError(0)},
5032+
{"=SQ=", true, false, "", base64.CorruptInputError(0)},
5033+
{"SQ", false, false, "", base64.CorruptInputError(0)},
5034+
{"SQ", true, false, "", base64.CorruptInputError(0)},
5035+
{"SQ=", false, false, "", base64.CorruptInputError(3)},
5036+
{"SQ=", true, false, "", base64.CorruptInputError(3)},
5037+
{"SQ===", false, false, "", base64.CorruptInputError(4)},
5038+
{"SQ===", true, false, "", base64.CorruptInputError(4)},
49955039
}
49965040

49975041
func TestBase64DecodeFunc(t *testing.T) {
@@ -5003,10 +5047,14 @@ func TestBase64DecodeFunc(t *testing.T) {
50035047
if testCase.IsURL {
50045048
encoding = base64.URLEncoding
50055049
}
5006-
encoding = encoding.Strict()
5050+
// sanity check:
5051+
if testCase.Error == nil && !testCase.HasExtraNLs {
5052+
require.Equal(t, testCase.Encoded, encoding.EncodeToString([]byte(testCase.Decoded)))
5053+
}
5054+
50075055
decoded, err := base64Decode([]byte(testCase.Encoded), encoding)
5056+
require.Equal(t, testCase.Error, err, fmt.Sprintf("Error (%s): case decode [%s] -> [%s]", err, testCase.Encoded, testCase.Decoded))
50085057
require.Equal(t, []byte(testCase.Decoded), decoded)
5009-
require.Equal(t, testCase.Error, err)
50105058
}
50115059
}
50125060

@@ -5026,9 +5074,9 @@ base64_decode %s
50265074
args := []b64DecodeTestArgs{}
50275075
for _, testCase := range testCases {
50285076
if testCase.Error == nil {
5029-
field := "StdAlph"
5077+
field := "StdEncoding"
50305078
if testCase.IsURL {
5031-
field = "URLAlph"
5079+
field = "URLEncoding"
50325080
}
50335081
source := fmt.Sprintf(sourceTmpl, minB64DecodeVersion, field)
50345082
ops, err := AssembleStringWithVersion(source, minB64DecodeVersion)

0 commit comments

Comments
 (0)