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
{{ message }}
Repository navigation
Crypto Hashm/Hmac digest segfault on bad input #9819
Both Hash's and Hmac's digest binding functions hard crash when given an object
that either defines a throwing getter or throwing toString. For example:
Internally, PraseEncoding calls encoding_v->IsString() without checking if
the value is Empty, hence the crash.
May be worth checking other callsites for ParseEncoding. The binding code for verify.verify() calls ParseEncoding too, but the actual encoding argument
from JS land is never passed in. (This is similar to the unused code I
mentioend in #9817, but for sign().)
After fixing this, I noticed that the crypto API is more or less the only part of node which uses ToString() on encodings. It might be better to simply drop support for toString(). The only edge case is
I don’t have a strong preference, but dropping toString() support might be semver-major – I find it hard to think of a scenario in which somebody might rely on it, but it’s hard to know for sure.
The version of ToString() that returns a Local is being deprecated exactly because of these error handling pitfalls (at least that’s what I assume), so the most direct approach would probably be switching to the MaybeLocal version and returning back to JS if the result is empty.
so the most direct approach would probably be switching to the MaybeLocal version and returning back to JS if the result is empty.
This is exactly how I fixed it.
Alternatively, we could do the conversion in crypto.js (String(outputEncoding) should be enough) and drop the additional logic in crypto.cc.
ParseEncoding will silently ignore all invalid values, unless they are empty. I'd suggest to add CHECK(!encoding_v.IsEmpty()) at the beginning of ParseEncoding even if we fix this specific problem in the crypto module.
@tniessen I think handling it properly in C++ as you did is the best way to do it, even if you end up doing casts in crypto.js. It's pretty easy to get at functions indirectly even if process.binding is hidden at some point.
Activity
tniessen commentedon Apr 2, 2017
After fixing this, I noticed that the crypto API is more or less the only part of node which uses
ToString()on encodings. It might be better to simply drop support fortoString(). The only edge case isbut this is consistent with other APIs:
If this is not okay, I can create a PR which correctly handles exceptions thrown when evaluating
toString().@addaleax Hope it's okay to ping you about this, what do you think? :)
addaleax commentedon Apr 2, 2017
I don’t have a strong preference, but dropping
toString()support might be semver-major – I find it hard to think of a scenario in which somebody might rely on it, but it’s hard to know for sure.The version of
ToString()that returns aLocalis being deprecated exactly because of these error handling pitfalls (at least that’s what I assume), so the most direct approach would probably be switching to theMaybeLocalversion and returning back to JS if the result is empty.And yes, it’s definitely okay to ping me. :)
tniessen commentedon Apr 2, 2017
This is exactly how I fixed it.
Alternatively, we could do the conversion in
crypto.js(String(outputEncoding)should be enough) and drop the additional logic incrypto.cc.ParseEncodingwill silently ignore all invalid values, unless they are empty. I'd suggest to addCHECK(!encoding_v.IsEmpty())at the beginning ofParseEncodingeven if we fix this specific problem in the crypto module.addaleax commentedon Apr 2, 2017
I feel like @bnoordhuis might be into that option. 😛
But really, everything you suggest here sounds okay to me – want to go ahead and open a PR?
deian commentedon Apr 2, 2017
@tniessen I think handling it properly in C++ as you did is the best way to do it, even if you end up doing casts in crypto.js. It's pretty easy to get at functions indirectly even if process.binding is hidden at some point.
Thank you both for going through these!
crypto: handle exceptions in hmac/hash.digest
crypto: handle exceptions in hmac/hash.digest
crypto: handle exceptions in hmac/hash.digest
test: use descriptive names for regression tests
test: use descriptive names for regression tests
test: use descriptive names for regression tests
test: use descriptive names for regression tests
crypto: handle exceptions in hmac/hash.digest