Skip to content

encoding/ascii85: Decode is wrong when the source is 1 or 5 bytes long #75590

@xformerfhs

Description

@xformerfhs

Go version

go version go1.25.1 windows/amd64

Output of go env in your module/workspace:

set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=0
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=
set GOAMD64=v3
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=
set GOCACHE=C:\Users\User\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\User\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=T:\UserTemp\User\go-build2668626540=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=D:\Users\User\go\src\cryptochallenge\go.mod
set GOMODCACHE=D:\Users\User\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=D:\Users\User\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=on
set GOTELEMETRYDIR=C:\Users\User\AppData\Roaming\go\telemetry
set GOTMPDIR=T:\UserTemp\User
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.25.1
set GOWORK=
set PKG_CONFIG=pkg-config

What did you do?

I wrote a program that had to encode data in various encodings. The data are byte slices with variable lengths. One of the encodings is ascii85. I used the standard package encoding/ascii85 for this. I noticed that the decoding was wrong in certain cases and wrote test cases for these:

package byteencoding

import (
	"encoding/ascii85"
	"testing"
)

func TestAscii85EncodeDecode1(t *testing.T) {
	src := []byte("Q")
	enc := make([]byte, ascii85.MaxEncodedLen(len(src)))
	nenc := ascii85.Encode(enc, src)
	enc = enc[0:nenc]
	dec := make([]byte, len(enc))
	ndec, _, err := ascii85.Decode(dec, enc, true)
	if err != nil {
		t.Fatal("Decode failed", err)
	}
	dec = dec[0:ndec]
	if ndec != len(src) {
		t.Fatalf("Decode(%q=Encode(%02x))=%02x returned wrong length. Expected %d, got %d",
			string(enc), src, dec, len(src), ndec)
	}
}

func TestAscii85EncodeDecode5(t *testing.T) {
	src := []byte("ABCDE")
	enc := make([]byte, ascii85.MaxEncodedLen(len(src)))
	nenc := ascii85.Encode(enc, src)
	enc = enc[0:nenc]
	dec := make([]byte, len(enc))
	ndec, _, err := ascii85.Decode(dec, enc, true)
	if err != nil {
		t.Fatal("Decode failed", err)
	}
	dec = dec[0:ndec]
	if ndec != len(src) {
		t.Fatalf("Decode(%q=Encode(%02x))=%02x returned wrong length. Expected %d, got %d",
			string(enc), src, dec, len(src), ndec)
	}
}

I think the culprit is this code right at the beginning of the Decode function:

	if len(dst)-ndst < 4 {
			return
		}

When I comment this out, everything works correctly.

What did you see happen?

When the data to be encoded has size 1 or 5 the encoded value is wrongly decoded. It is one byte short. E.g.

  • []byte(0x41, 0x42, 0x43, 0x44, 0x45) correctly encoded to "5sdq,70", incorrectly decoded to []byte(0x41, 0x42, 0x43, 0x44).
  • []byte(0x51) correctly encoded to ";#", incorrectly decoded to []byte().

This happens with all data of length 1 and 5.

What did you expect to see?

The data should be correctly decoded. E.g.

  • "5sdq,70" should be decoded to []byte(0x41, 0x42, 0x43, 0x44, 0x45).
  • ";#", should be decoded to []byte(0x51).

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions