Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting an "index out of range" error when base64 encoding a byte array?

Tags:

arrays

base64

go

When encoding a byte array into a base64 byte array, the below code produces a runtime index out of range error. How can this be resolved?

package main

import (
    "fmt"
    "encoding/base64"
)

func main() {
    data := []byte("string of data")
    var encodedData []byte
    base64.StdEncoding.Encode(encodedData, data)
    fmt.Println(encodedData)
}

Playground here

like image 436
jsc Avatar asked May 03 '17 23:05

jsc


People also ask

Why can’t I decode a base 64 string with one alphabet?

An encoded string with one alphabet may not be decoded using the other alphabet’s decoding system. If the decoder attempts to read an unrecognized character, it’ll send an Illegal base64 character error message. You can’t decode a Base 64 URL string with the fromBase64 DataWeave 2.0 function.

How to decode byte array with Base64 content in Java?

To decode byte array which contais base64 content you can use javax.xml.bind.DatatypeConverter. It works pretty well. I use it to decode MongoDB values of binary type.

Why is my index out of range in a list?

indexwill now be out of range in the last loop iteration, because the loop thinks that Lengthis a valid index, but it is not. How other collections work Lists work the same way, except that you generally use Countinstead of Length. They still start at zero, and end at Count - 1.

How to convert a string to a Base64 string?

It's Java's string representation of the object (for example, " [B@9a4d5c6" ). You need to do what iccthedral suggest and provide the bytes to a String class. If you are using Android API 8+ there's a Base64 helper class in android.util. String stringToStore = Base64.encodeToString (cipherText, Base64.DEFAULT);


Video Answer


3 Answers

The error is:

panic: runtime error: index out of range

goroutine 1 [running]:
encoding/base64.(*Encoding).Encode(0xc420056000, 0x0, 0x0, 0x0, 0xc42003bf30, 0xe, 0x20)
        /usr/lib/go/src/encoding/base64/base64.go:113 +0x27b
main.main()
        /home/martin/a.go:11 +0x9b
exit status 2

shell returned 1

If we look at /usr/lib/go/src/encoding/base64/base64.go line 113, we see (abbreviated):

n := (len(src) / 3) * 3
for si < n {
    // [..]
    dst[di+0] = enc.encode[val>>18&0x3F]
    dst[di+0] = enc.encode[val>>18&0x3F]
    dst[di+1] = enc.encode[val>>12&0x3F]
    // [..]
}

In other words, this function directly sets the index of dst. The length of var encodedData []byte is zero, so you get the index out of range error.

One way to fix it would be to change the line to:

encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))

Which will make an array of the size in the second argument. Base64 encoded data is larger than the input, hence the base64.StdEncoding.EncodedLen().

However, this is hardly the best way to fix it. The documentation mentions:

Encode is not appropriate for use on individual blocks of a large data stream. Use NewEncoder() instead.

Rewriting the code to NewEncoder() looks like:

func main() {
    data := []byte("string of data")

    encodedData := &bytes.Buffer{}
    encoder := base64.NewEncoder(base64.StdEncoding, encodedData)
    defer encoder.Close()
    encoder.Write(data)

    fmt.Println(encodedData)
}

There also some other useful functions, such as EncodeToString() which make the above a bit shorter and more convenient: encodedData := base64.StdEncoding.EncodeToString(data).

like image 190
Martin Tournoij Avatar answered Oct 20 '22 18:10

Martin Tournoij


Allocate space for the output. For example,

package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    data := []byte("string of data")
    encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
    base64.StdEncoding.Encode(encodedData, data)
    fmt.Println(encodedData)
}

Output:

[99 51 82 121 97 87 53 110 73 71 57 109 73 71 82 104 100 71 69 61]

var encodedData []byte is zero bytes. Therefore, index out of range

like image 25
peterSO Avatar answered Oct 20 '22 20:10

peterSO


Because Encode expects the dst slice to be allocated to the correct length.

Encode encodes src using the encoding enc, writing EncodedLen(len(src)) bytes to dst.

like image 1
mkopriva Avatar answered Oct 20 '22 19:10

mkopriva