Skip to content

Conversation

@wking
Copy link
Contributor

@wking wking commented Jun 9, 2017

This error was added in 9721254 (Validate digest length on parsing, 2015-12-02) and motivated with:

The new error is mostly so that digest.Set doesn't need a special way to figure out if invalid digest had a algorithm prefix or not.

That doesn't make sense to me, because Digest.Validate returns ErrDigestUnsupported when there is no algorithm prefix (I've added a test to confirm this as well), and that seems orthogonal to encoding validation (which is the only place ErrDigestInvalidLength could matter). From the other changes in distribution/distribution#1231, I think the issue was just that invalid lengths weren't raising errors at all.

I see no reason to distinguish between invalid lengths, invalid characters, and other invalid-encoded-portion errors, so this commit collapses the error into ErrDigestInvalidFormat.

The code I'm removing assumed hex (with .Size() * 2), so this PR removes that assumption. The sha256 and other hex-based algorithms are still getting their lengths validated via anchoredEncodedRegexps.

This PR is based on my earlier suggestion. I think @AkihiroSuda kept the error because of @stevvooe's comment:

This needs to remain. Are we no longer throwing this error?

but with this PR we will continue throwing an error in the invalid-length case and folks who are switching on ErrDigestInvalidLength can continue to do so. It's just that they'll no longer be able to distinguish between ErrDigestInvalidLength and ErrDigestInvalidFormat, and since I see no reason to do that, I don't see it as an important backwards-compat concern. If someone does have a reason to make that distinction, pointing at that code would be a good reason to close this PR.

This error was added in 9721254 (Validate digest length on parsing,
2015-12-02) and motivated with [1]:

> The new error is mostly so that digest.Set doesn't need a special
> way to figure out if invalid digest had a algorithm prefix or not.

That doesn't make sense to me, because Digest.Validate returns
ErrDigestUnsupported when there is no algorithm prefix (I've added a
test to confirm this as well), and that seems orthogonal to encoding
validation (which is the only place ErrDigestInvalidLength could
matter).  From the other changes in [1], I think the issue was just
that invalid lengths weren't raising errors at all.

I see no reason to distinguish between invalid lengths, invalid
characters, and other invalid-encoded-portion errors, so this commit
collapses the error into ErrDigestInvalidFormat.

The code I'm removing assumed hex (with '.Size() * 2'), so this commit
removes that assumption. The sha256 and other hex-based algorithms are
still getting their lengths validated via anchoredEncodedRegexps.

[1]: distribution/distribution#1231

Signed-off-by: W. Trevor King <wking@tremily.us>
@wking wking force-pushed the deprecate-ErrDigestInvalidLength branch from b297dcc to 1167650 Compare June 9, 2017 21:35
@dmcgowan
Copy link
Member

dmcgowan commented Jun 9, 2017

I agree that throwing 2 different errors with similar meaning is not the way to go. Clients who are interested in these values would then have to check 2 separate values, although likely when they were created separately it was assumed that clients would not be switching off invalid data (not actionable) and just propagating the error or discarding the value. A better solution involves wrapping such as github.com/pkg/errors, but we are not going to pull in a vendor to this package. The best thing we can probably do now is just close this PR and revisit it if pkg/errors is upstreamed into golang or when we add support for other encodings and need logic smarter than .Size() * 2 to determine the expected size. No longer throwing the invalid length error just reduces the messaging to the callers, who are very unlikely to be switching off these error messages anyway. Checking 2 values instead of 1 is not ideal if they are, but it is not worth reducing the error granularity or adding error type complexity.

@wking
Copy link
Contributor Author

wking commented Jun 9, 2017 via email

@stevvooe
Copy link
Contributor

@wking Length and format errors are fundamentally different. This PR is fairly naive.

@stevvooe stevvooe closed this Jun 10, 2017
@wking
Copy link
Contributor Author

wking commented Jun 10, 2017

Length and format errors are fundamentally different.

Maybe in some cases. For example, sha256:abcdef0123456789 is too short, but otherwise fine, so I'm fine expecting the ErrDigestInvalidLength it actually returns. And sha256:E58FCF7418D4390DEC8E8FB69D88C06EC07039D651FEDD3AA72AF9972E7D046B is the right length, and has only invalid characters (uppercase hex), so I'm fine expecting the ErrDigestInvalidFormat it actually returns. But there are a number of murky corner cases, and it's not obvious to me from the error docs what to expect in the following cases:

So to find potential effects due to these murky cases, let's look for some consumers distinguishing between the two cases:

opencontainers/image-spec $ git grep 'ErrDigestInvalid[FL]' v1.0.0-rc6
…no hits…
opencontainers/image-tools $ git grep 'ErrDigestInvalid[FL]' 38db2e4 | grep -v /go-digest/
…no hits…
opencontainers/runc $ git grep 'ErrDigestInvalid[FL]' v1.0.0-rc3
…no hits…
opencontainers/containerd $ git grep 'ErrDigestInvalid[FL]' v0.2.8
…no hits…
moby/moby $ git grep 'ErrDigestInvalid[FL]' v17.05.0-ce | grep -v '/go-digest/\|/docker/distribution/'
…no hits…
docker/distribution$ git grep 'ErrDigestInvalid[FL]' v2.6.1 | grep -v '^v2.6.1:digest/'
v2.6.1:reference/reference.go:  // ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
v2.6.1:reference/reference.go:  ErrDigestInvalidFormat = errors.New("invalid digest format")
v2.6.1:reference/reference.go:          return nil, ErrDigestInvalidFormat
v2.6.1:reference/reference_test.go:                     err:   digest.ErrDigestInvalidLength,
v2.6.1:registry/handlers/images.go:                                     if verificationError == digest.ErrDigestInvalidFormat {
v2.6.1:registry/handlers/images.go:             case digest.ErrDigestInvalidFormat:
v2.6.1:registry/storage/cache/cachecheck/suite.go:              MediaType: "application/octet-stream"}); err != digest.ErrDigestInvalidFormat {
v2.6.1:registry/storage/cache/cachecheck/suite.go:      if _, err := cache.Stat(ctx, ""); err != digest.ErrDigestInvalidFormat {

Going through those:

So of the docker/distribution cases, one is a wrapping validation framework that defines its own ErrDigestInvalidFormat for both length and valid-char errors, one has a pretty API version of ErrDigestInvalidFormat but none for ErrDigestInvalidLength, one disagrees with our master about the error (for sha384:abc), and two agree with our master about the error (for the empty digest and sha256:ffffffffffffffffffffffffffffffffff). That doesn't seem like a ringing endorsement for “these are fundamentally different” to me.

So is there anywhere that this distinction matters? The only downstream effect I can see for this consolidation is that it would be improved errors in the docker/distribution API. Are there any consumers that would be negatively impacted by this change?

@stevvooe
Copy link
Contributor

stevvooe commented Sep 8, 2017

@wking The problem with this PR is that it removes the size check. That is not required to deprecate the length error.

@wking
Copy link
Contributor Author

wking commented Sep 14, 2017

The problem with this PR is that it removes the size check.

No it doesn't. We're still checking size here, used here. Also note that all the old unit tests still raise the expected error; none are failing to raise an error. If you feel it is missing a case, feel free to propose a new test case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants