-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
module: fix recently introduced coverity warning #50843
Conversation
Signed-off-by: Michael Dawson <[email protected]>
Coverity warning - 3. Condition error, taking false branch.
4. Condition simdjson::simdjson_result<simdjson::fallback::ondemand::object>(document.get_object()).get(main_object), taking false branch.
141 if (error || document.get_object().get(main_object)) {
142 return throw_invalid_package_config();
143 }
144
5. write_zero_model: raw_json_string sets key.buf to nullptr. [[show details](https://scan9.scan.coverity.com/eventId=9481392-7&modelId=9481392-0&fileInstanceId=124214292&filePath=%2Fdeps%2Fsimdjson%2Fsimdjson.h&fileStart=38692&fileEnd=38692)]
145 simdjson::ondemand::raw_json_string key;
146 simdjson::ondemand::value value;
147 std::string_view field_value;
148 simdjson::ondemand::json_type field_type;
149
6. Iterating over another element of main_object.
150 for (auto field : main_object) {
151 // Throw error if getting key or value fails.
7. Condition simdjson::simdjson_result<simdjson::fallback::ondemand::raw_json_string>(field.key()).get(key), taking false branch.
8. Condition simdjson::simdjson_result<simdjson::fallback::ondemand::value>(field.value()).get(value), taking false branch.
152 if (field.key().get(key) || field.value().get(value)) {
153 return throw_invalid_package_config();
154 }
155
CID 331027 (#1 of 1): Explicit null dereferenced (FORWARD_NULL)
9. var_deref_model: Passing key to operator ==, which dereferences null key.buf. [[show details](https://scan9.scan.coverity.com/eventId=9481392-13&modelId=9481392-1&fileInstanceId=124214292&filePath=%2Fdeps%2Fsimdjson%2Fsimdjson.h&fileStart=44376&fileEnd=44378)]
156 if (key == "name") { |
I had tried to do the check in the earlier check for an invalid package config. That caused failures so I think that means that key.raw() is null in some cases and even though we dereffed those we got lucky because the contents never mached what we were checking against. |
The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new check is cheap. It should never fire in practice.
It really shouldn't be null... I wonder if the coverage tool got confused by the ||? if (field.key().get(key) || field.value().get(value)) { That said, the extra check isn't expensive or super objectionable (certainly don't let it get in the way of writing nodejs). It's just either unnecessary or Very Very Bad. If a successful key can point to null then a while lot of things will go wrong in a lot of people's code. Might be a SIMDJSON_ASSUME needs to be inserted to keep coverity sane. |
(I'll take a look at the simdjson side to see if there are any holes anywhere, but don't let that stop this train.) |
Looking through it, the for loop ( const uint8_t *key = _json_iter->return_current_and_advance();
if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
return raw_json_string(key); If coverity was checking the simdjson code itself I might expect it to squawk at |
If this theory is correct, coverity should trigger anytime you ever try to access a key while iterating over a simdjson object. Adding a The if () you added will suffice, though I hope the compiler can be told that it's not an issue so that it can optimize this (and other similar checks) away. That's one of the great things about having padding. |
@mhdawson how does one reproduce this? The CI checks in main are succeeding--does coverity run on this code in CI or does one need to run something extra when compiling? |
@jkeiser coverity runs as a separate job in - https://ci.nodejs.org/job/node-daily-coverity/. Unfortunately, we've not found a way to easily run it locally. What I think you could do is add the null check in the earlier line if (field.key().get(key) || field.value().get(value)) { and then run the Node.js test suite (make node test) That is what I had tried to do earlier and which resulted in failures when I ran the Node.js test suite. If you see the failures it should confirm that the null can happen in some cases. I'll land this which will at least quiet the coverity warning and if you find I messed up my earlier check you can submit a PR to move the code into a better way of addressing the warning. |
Signed-off-by: Michael Dawson <[email protected]> PR-URL: #50843 Reviewed-By: James M Snell <[email protected]>
Landed in d4bcdd8 |
Yeah, I really want to know if null is possible, because it's not designed to be possible--this is either a bug or a limitation with coverity. Particularly the key of a field: you absolutely shouldn't be given a field object in the first place unless there is a quote, and if there is a quote there is definitely enough padding and a whole string (otherwise the parser.iterate call would have failed. |
(And in the meantime merging is the right thing.) |
Here is what I just did. I got the latest node code (from the main branch). I made the following change... index 9217b94852e..41359b0de1b 100644
--- a/src/node_modules.cc
+++ b/src/node_modules.cc
@@ -155,8 +155,11 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON(
// based on coverity using key with == derefs the raw value
// avoid derefing if its null
- if (key.raw() == nullptr) continue;
-
+// if (key.raw() == nullptr) continue;
+ if (key.raw() == nullptr) {
+ printf("bug with '.*s'\n", package_config.raw_json.size(), package_config.raw_json.data());
+ abort();
+ }
if (key == "name") {
// Though there is a key "name" with a corresponding value,
// the value may not be a string or could be an invalid JSON string I typed...
This takes a few minutes (but only the first time, if you have already built the project, making changes and hitting make again is fast). I then typed...
(To go faster do This is on a Linux and AVX-512 capable x64 box. GCC 12. I get one failure that is unrelated...
The end result is... @mhdawson Do you find anything wrong in what I described above? My current hypothesis is that it is a false positive. I think that coverity thinks that we can dereference a null pointer, but that's because it fails to do a complete analysis. There are false positives with coverity: https://community.synopsys.com/s/article/REVERSE-INULL-False-Positive-Dereference-before-NULL-check So it would not be surprising if it were a false positive. |
Signed-off-by: Michael Dawson <[email protected]> PR-URL: #50843 Reviewed-By: James M Snell <[email protected]>
to land on v20 dependes on #50965 |
No description provided.