go-crypt
go-crypt copied to clipboard
Sucessful calls might return an error value
According to the docs:
Any C function (even void functions) may be called in a multiple assignment context to retrieve both the return value (if any) and the C
errnovariable as an error
But crypt() does not set errno, and the call to C.crypt() is building a error variable with a value of some other call. If errno is not 0, then err is not nil. Both
https://github.com/amoghe/go-crypt/blob/master/crypt.go#L41
and
https://github.com/amoghe/go-crypt/blob/master/crypt.go#L48
are returning an unrelated value.
So this code might or might fail:
password, err := Crypt(password, salt)
if err != nil {
// TODO: oh no!
log.Printf("crypt: [%v] %v", password, err)
return err
}
Like this:
2019/11/12 05:56:42 $6$iq.dbF2KUB2h, x
2019/11/12 05:56:42 crypt: [$6$iq.dbF2KUB2h$nV.xPcJUqHN1r46FQ/MJJc7OVbSb5Yd4nsOLU.XZ3QsVdwgGjqVoNeEx.u8MIFC1seQcS8jAelI95Z8BlBmeC/] errno -8191
Hmmm, hold that thought, crypt() is supposed to set errno, hmmm....
What I gleaned from the documentation is that:
- if crypt (or any other libc call) returns with no exitcode, then do NOT look at errno, it may not be cleared and may still hold the last error
- if crypt returns an error, then errno will be set
and thats how this library behaves w.r.t errors from libc
Yeah, but that breaks the golang way. The usual thing to do when wrapping for a language is to follow the patterns of that language, otherwise anyone using it finds it surprising, like in this case. Of course, it's your code, so you're free to decide that. Just try to add a note somewhere that it was a conscious decision. Maybe just point to this issue and close it.
Do you have any thoughts/suggestions on how to structure the code better to avoid this confusion?
Well, golang's pattern here is that you do:
result, err := call(params)
if err != nil {
// handle error
}
So just
return C.GoString(c_enc), nil
in line 48.