You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hey, I'm working on re-writing the Object Store client implementation from Golang to Python, and I think I found a bug in the golang's implementation of ObjectStore.Get API. Near the end of this API call, there is a code that performs a digest check between the content it just obtained from NATS, and the digest saved in ObjectInfo instance:
But the value of info.Digest is equal to something like sha-256=X7IFRHg1P9jVFAVtF0Wzqe7wZt6t2kuQlnr3ymXOZQU= because it was created by this line in the ObjectStore.Put API call:
Because of that, the digest validation always fails in the Get API call, because the string that gets decoded into an SHA is not a valid Base64 value.
But what is worse, it looks like this error is not even propagated correctly into the calling code because of a race condition. I created a small sample that visualizes this problem and attached it below. I had to modify the Get API call with some additional print statements to visualize this issue.
Could someone confirm if that is indeed an issue, or if I'm misunderstanding something about how it should be used?
Thanks in advance!
Versions of nats.go and the nats-server if one was involved:
github.com/nats-io/nats.go v1.16.0 NATS-Server version 2.8.2
OS/Container environment:
Tested on MacOS, but I think this error occurs on all environments.
I also modified my local version of func (obs *obs) Get(name string, opts ...ObjectOpt) (ObjectResult, error) function with additional prints lines to better visualize the problem:
// Get will pull the object from the underlying stream.func (obs*obs) Get(namestring, opts...ObjectOpt) (ObjectResult, error) {
// Grab meta info.info, err:=obs.GetInfo(name)
iferr!=nil {
returnnil, err
}
ifinfo.NUID==_EMPTY_ {
returnnil, ErrBadObjectMeta
}
// Check for object links.If single objects we do a pass through.ifinfo.isLink() {
ifinfo.ObjectMeta.Opts.Link.Name==_EMPTY_ {
returnnil, errors.New("nats: link is a bucket")
}
lobs, err:=obs.js.ObjectStore(info.ObjectMeta.Opts.Link.Bucket)
iferr!=nil {
returnnil, err
}
returnlobs.Get(info.ObjectMeta.Opts.Link.Name)
}
varoobjOptsfor_, opt:=rangeopts {
ifopt!=nil {
iferr:=opt.configureObject(&o); err!=nil {
returnnil, err
}
}
}
ctx:=o.ctxresult:=&objResult{info: info, ctx: ctx}
ifinfo.Size==0 {
returnresult, nil
}
pr, pw:=net.Pipe()
result.r=prgotErr:=func(m*Msg, errerror) {
pw.Close()
m.Sub.Unsubscribe()
result.setErr(err)
}
// For calculating sum256h:=sha256.New()
processChunk:=func(m*Msg) {
ifctx!=nil {
select {
case<-ctx.Done():
ifctx.Err() ==context.Canceled {
err=ctx.Err()
} else {
err=ErrTimeout
}
default:
}
iferr!=nil {
gotErr(m, err)
return
}
}
tokens, err:=getMetadataFields(m.Reply)
iferr!=nil {
gotErr(m, err)
return
}
// Write to our pipe.forb:=m.Data; len(b) >0; {
n, err:=pw.Write(b)
iferr!=nil {
gotErr(m, err)
return
}
b=b[n:]
}
// Update sha256h.Write(m.Data)
// Check if we are done.iftokens[ackNumPendingTokenPos] ==objNoPending {
fmt.Println("call1")
pw.Close()
fmt.Println("call2")
m.Sub.Unsubscribe()
fmt.Println("call3")
// Make sure the digest matches.sha:=h.Sum(nil)
fmt.Println("call4", sha, info.Digest)
rsha, err:=base64.URLEncoding.DecodeString(info.Digest)
fmt.Println("call5", rsha)
iferr!=nil {
fmt.Println("call6!", err)
gotErr(m, err)
return
}
fmt.Println("call7", err)
if!bytes.Equal(sha[:], rsha) {
gotErr(m, ErrDigestMismatch)
return
}
}
}
chunkSubj:=fmt.Sprintf(objChunksPreTmpl, obs.name, info.NUID)
_, err=obs.js.Subscribe(chunkSubj, processChunk, OrderedConsumer())
iferr!=nil {
returnnil, err
}
returnresult, nil
}
As you can see the call7 never got called, even though I was just putting and getting an object from the ObjectStore. Also, print statements "RES ERR" & "RES ERR2" both times printed indicating that there was no error while getting object from the object store, even though call6! print statement indicates otherwise.
The text was updated successfully, but these errors were encountered:
Defect
Hey, I'm working on re-writing the Object Store client implementation from Golang to Python, and I think I found a bug in the golang's implementation of
ObjectStore.Get
API. Near the end of this API call, there is a code that performs a digest check between the content it just obtained from NATS, and the digest saved inObjectInfo
instance:But the value of
info.Digest
is equal to something likesha-256=X7IFRHg1P9jVFAVtF0Wzqe7wZt6t2kuQlnr3ymXOZQU=
because it was created by this line in theObjectStore.Put
API call:Because of that, the digest validation always fails in the
Get
API call, because the string that gets decoded into an SHA is not a valid Base64 value.But what is worse, it looks like this error is not even propagated correctly into the calling code because of a race condition. I created a small sample that visualizes this problem and attached it below. I had to modify the
Get
API call with some additional print statements to visualize this issue.Could someone confirm if that is indeed an issue, or if I'm misunderstanding something about how it should be used?
Thanks in advance!
Versions of
nats.go
and thenats-server
if one was involved:github.com/nats-io/nats.go v1.16.0
NATS-Server version 2.8.2
OS/Container environment:
Tested on MacOS, but I think this error occurs on all environments.
Steps or code to reproduce the issue:
Small code sample that presents the bug:
I also modified my local version of
func (obs *obs) Get(name string, opts ...ObjectOpt) (ObjectResult, error)
function with additional prints lines to better visualize the problem:This produced the following output in my console:
As you can see the
call7
never got called, even though I was just putting and getting an object from the ObjectStore. Also, print statements "RES ERR" & "RES ERR2" both times printed indicating that there was no error while getting object from the object store, even thoughcall6!
print statement indicates otherwise.The text was updated successfully, but these errors were encountered: