-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Address issues picked up by Dev15 code analysis #5272
Address issues picked up by Dev15 code analysis #5272
Conversation
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.
Looks good, just a couple of questions.
{ | ||
script = new char[fileSize + 1]; | ||
script = new char[(size_t)fileSize + 1]; |
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.
Is this required?
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.
Array size declarations are size_t, and the analysis gets unhappy if we have a different type used in the addition here before the implicit conversion. This is notable for types shorter than size_t, as the overflow would occur before the conversion to size_t. I believe that on all currently-supported platforms this is indeed not required.
@@ -11,7 +11,7 @@ namespace Js | |||
SIMDValue SIMDBool32x4Operation::OpBool32x4(bool x, bool y, bool z, bool w) | |||
{ | |||
X86SIMDValue x86Result; | |||
x86Result.m128i_value = _mm_set_epi32(w * -1, z * -1, y * -1, x * -1); | |||
x86Result.m128i_value = _mm_set_epi32((w?1:0) * -1, (z?1:0) * -1, (y?1:0) * -1, (x?1:0) * -1); |
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.
Could this be simpler?
_mm_set_epi32(w?-1:0, z?-1:0, y?-1:0, x?-1:0)
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.
Yes, you're correct, I'll fix that in the next update.
@@ -194,7 +194,7 @@ namespace Js | |||
|
|||
Waiters * m_waiters; | |||
|
|||
// Below CS is used for synchronizig access in wait/wake API | |||
// Below CS is used for synchronizing access in wait/wake API |
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.
Prefast finds typos now?
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.
Drive-by clean-up.
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.
That being said, there are tools that spell-check comments, but I doubt that we'd find much benefit from using them.
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.
I was just taking the opportunity to make a joke. We have typos in comments all over but fixing them like this - as a one-off thing - is probably best.
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.
Ah, sorry. 👍
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.
np 👌
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.
We actually did use some spell checker tools and manual review of comments and names to clean up before we open-sourced ChakraCore. We didn't catch everything and got some PRs early on fixing other typos, and more typos have creeped in since then. I support drive-by clean up. :)
getset = true; | ||
} | ||
if (descriptor->GetSetterPropertyIndex() != NoSlots) | ||
{ | ||
*setter = instance->GetSlot(descriptor->GetSetterPropertyIndex()); | ||
if(!getset) { | ||
// if we didn't set the getter above, we need to set it here |
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.
getter
is an out param, right? How can we get away without setting it on all paths here? Why not just assign it and setter
as well to nullptr right at the top of this function and then we don't care if it was set in above conditional?
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.
Due to the _Success_(return)
annotation, the outparam annotations are only required to be valid if the function returns true. I agree that it's a bit poorly designed, but the primary goal here was to align things with existing annotations.
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.
Alright but I object to the silliness of that annotation.
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.
Can we have a getter without a setter, or vice versa? I thought that internally we constructed them in pairs, even if one was a stub "I don't exist, why are you calling me" function.
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.
Since if(!getset)
looks like new code, can we use the existing convention (and preferred by many) of putting a space in if (
?
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.
Also put the {
on a new line, while you're at it.
By the way, should this make it into release/1.10 or hold on until after we cut that branch? |
I'm leaning toward putting it in master after the 1.10 cut. The downside of that is that we may end up with changes to release/1.10 breaking the CI when pumped, but that shouldn't be too common. |
@@ -74,12 +74,18 @@ CompileAssert(false) | |||
#define MCGEN_PRIVATE_ENABLE_CALLBACK_V2(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) \ | |||
EtwCallback(ControlCode, CallbackContext) | |||
|
|||
// Work-around for a bug in the instrumentationevents generator | |||
#pragma prefast(push) | |||
#pragma prefast(disable:__WARNING_USING_UNINIT_VAR, "The ETW data generated from the manifest includes a default null function which uses unintialized memory.") |
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.
Is this because of how our manifest is structured, or would any project using ETW hit this same warning?
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.
I'm not entirely sure. I wasn't able to see a good way to fix it by changing the manifest, so I believe that it may be across many projects using ETW in a similar manner.
void _Releases_lock_(cs.cs) EndResize() {} | ||
private: | ||
// For prefast analysis, we need to have a somewhat similar shape for both locks | ||
Field(contentStruct) cs; |
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.
This is a bit of a bummer, having to waste some space for no real reason. I'm not super familiar with the semantics of SAL locking annotations; would it make sense to refer to this
instead of the actual lock (or the fake lock here), and elsewhere treat the various lock classes as critical sections / things-that-get-locked?
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.
As for the memory concern, how common is this object? We tend not to worry about memory usage in objects that have very few instances. Additionally, maybe we can add TODO comments to clean up issues like this if possible at a later time, since the scope of this PR is to unblock Dev15 PreFAST analysis.
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.
It's on most of our native Dictionary classes. I was also somewhat concerned that it might change the memory layout in a meaningful way, but there are some static asserts that check for that so it seems to be fine.
As for the number of native dictionaries we have, it's probably more like tens than tens of thousands, so the actual impact is probably small, but I don't have solid numbers to back that up at the moment.
I do agree that my comment here shouldn't block the PR.
@@ -61,7 +61,7 @@ namespace DateTime | |||
uint32 lastTimeZoneUpdateTickCount; | |||
|
|||
void UpdateTimeZoneInfo(); | |||
UtilityPlatformData(): lastTimeZoneUpdateTickCount(0) { } | |||
UtilityPlatformData() : lastTimeZoneUpdateTickCount(0) { GetTimeZoneInformation(&timeZoneInfo); } |
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.
Instead of directly calling GetTimeZoneInformation
here, would it be acceptable to call UpdateTimeZoneInfo
to do it instead?
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 conditional in UpdateTimeZoneInfo may make it such that the analysis can't be sure that we've initialized timeZoneInfo by the end of the constructor, which is what this code tries to avoid.
@@ -61,7 +61,7 @@ namespace Js | |||
virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override { return true; } | |||
virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, EnumeratorCache * enumeratorCache = nullptr); | |||
virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None) override { return false; } | |||
virtual BOOL GetAccessors(PropertyId propertyId, Var *getter, Var *setter, ScriptContext * requestContext) override { return false; } | |||
virtual BOOL GetAccessors(PropertyId propertyId, __out Var *getter, __out Var *setter, ScriptContext * requestContext) override { getter = nullptr; setter = nullptr; return false; } |
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.
Should this be *getter = nullptr; *setter = nullptr
?
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.
Yes, probably, and with a check on whether the pointers passed in are not nullptr before assigning to them.
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.
Ideally these should have been statically verified as non-null because we said Out and not Out_opt, right?
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.
Also, same pattern is in SpreadArgument.h
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.
*getter = nullptr; *setter = nullptr
would indeed be more correct, but the next set of commits avoids the issue entirely by making the function _Success_(return) _Check_return_
, and not assigning to either, as the result is always false.
@@ -2158,6 +2158,7 @@ namespace Js | |||
::Math::DefaultOverflowPolicy(); |
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.
Should this use UInt16Math
instead?
bin/ch/RuntimeThreadData.cpp
Outdated
@@ -25,10 +25,17 @@ RuntimeThreadData::RuntimeThreadData() | |||
this->hevntInitialScriptCompleted = CreateEvent(NULL, TRUE, FALSE, NULL); | |||
this->hevntReceivedBroadcast = CreateEvent(NULL, FALSE, FALSE, NULL); | |||
this->hevntShutdown = CreateEvent(NULL, TRUE, FALSE, NULL); | |||
this->hSemaphore = nullptr; | |||
this->hThread = nullptr; |
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.
is there a reason not to do these in an initializer list, or better yet, in class initialization?
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.
Yeah, changed in next commit.
I'd prefer before the cut (this change included in 1.10) so that 1.10 can have modern CI config enabled. |
For reference the payload we'll be merging to update CI so that modern is Dev15 and Legacy is Dev14 is in #4767 -- we'll retarget that to whichever branch this change lands in. |
What do we do about making changes to this file into permanent updates -- should we find the source that generated this file and PR back, or just say we need this update and we're not planning to regen this file? Refers to: bin/External/catch.hpp:6 in 7a9b9ea. [](commit_id = 7a9b9ea, deletion_comment = False) |
@@ -1243,7 +1244,8 @@ namespace JsRTApiTest | |||
size_t length; | |||
REQUIRE(JsStringToPointer(nameValue, &name, &length) == JsNoError); | |||
|
|||
CHECK(length == 1); | |||
REQUIRE(length == 1); | |||
#pragma prefast(suppress:__WARNING_MAYBE_UNINIT_VAR, "The require on the previous line should ensure that name[0] is initialized") |
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.
__WARNING_MAYBE_UNINIT_VAR [](start = 25, length = 26)
Did not all warnings have these fancy named macros? (There are some you're still suppressing or disabling by number)
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.
Nope, not all of them do. There are a couple cases where I missed using the named macro, though, that I should be fixing up in the next set of commits.
bin/ch/HostConfigFlags.cpp
Outdated
@@ -96,6 +96,7 @@ void HostConfigFlags::RemoveArg(int& argc, _Inout_updates_to_(argc, argc) LPWSTR | |||
Assert(index >= 0 && index < argc); | |||
for (int i = index + 1; i < argc; ++i) | |||
{ | |||
#pragma prefast(suppress:6385, "Operation is safe but PREfast is difficult to convince") |
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.
6385 [](start = 25, length = 4)
suppress warning by name macro instead of number?
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.
Done in next set of commits.
@@ -35,6 +35,7 @@ | |||
#endif // FreeBSD or unix ? | |||
#endif // _WIN32 ? | |||
|
|||
#pragma prefast(disable:26444, "This warning unfortunately raises false positives when auto is used for declaring the type of an iterator in a loop.") |
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.
26444 [](start = 24, length = 5)
suppress by name macro instead of number?
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.
No macro for this one, unfortunately.
Regarding the catch.hpp change; looks like their upstream has that fix (or an equivalent fix at least): https://github.com/catchorg/Catch2/blob/master/single_include/catch.hpp#L10054 They even changed for this same reason: catchorg/Catch2@88a6ff0 |
freq(0), | ||
fReset(true), | ||
fInit(false), | ||
fHiResAvailable(true) |
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.
was there a warning about initialization order or is this just drive-by cleanup?
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.
It's mostly drive-by; there's a warning in razzle prefast, and it helps for checking that there's no other uninitialized values when they're in the right order. We do not have initialization order warnings enabled in our jenkins runs.
@@ -2178,13 +2179,19 @@ namespace Js | |||
calleeInfo.Flags = (CallFlags)(calleeInfo.Flags | CallFlags_ExtraArg | CallFlags_NewTarget); | |||
} | |||
|
|||
for (uint argCount = 0; argCount < args.Info.Count; argCount++) | |||
for (ushort argCount = 0; argCount < (ushort)args.Info.Count; argCount++) |
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.
args.Info.Count [](start = 57, length = 15)
is it safe to cast args.Info.Count to ushort? If so, can we make args.Info.Count have the correctly-sized type?
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.
Further up around https://github.com/Microsoft/ChakraCore/pull/5272/files#diff-771647fb11e03690664371970f34eeaaR2126 we check that the value fits in a ushort and throw an error if it doesn't. We do allow for larger argument counts in some circumstances though, so args.Info.Count
is a uint.
AnalysisAssert(argCount < (ushort)args.Info.Count); | ||
AnalysisAssert(sizeof(Var*) == sizeof(void*)); | ||
AnalysisAssert(sizeof(Var*) * argCount < sizeof(void*) * newCount); | ||
#pragma prefast(suppress:__WARNING_WRITE_OVERRUN, "This is a false positive, and all of the above analysis asserts still didn't convince prefast of that.") |
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.
have we opened bugs for false positives?
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.
Not yet; I need to determine where we'd open bugs for these, and what would constitute an actionable report.
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.
🕐
We had signed/unsigned mixups between the format string and the args.
Note that this includes functional changes to one implementation, as it could in some cases only set the getter or setter and leave the other uninitialized. There's also a couple other function annotation alignment fixes in this commit.
Unfortunately there's a good number of holes, which seem to be due to how the PREfast analysis of the locking works. Someone familiar with the mechanics may be able to do this with fewer suppressions.
A pre-defined function is added to the chakra etw header that does not initialize a buffer before passing it around. It looks ok, but the warning is in a file that we have limited control over. Here I disabled the warning for the whole included file, which seems like the closest we can scope it.
7a9b9ea
to
2551132
Compare
2551132
to
80438b7
Compare
@@ -13,14 +13,14 @@ template <class T> | |||
class WeightedTable | |||
{ | |||
public: | |||
WeightedTable() : | |||
WeightedTable() noexcept : |
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.
noexcept [](start = 20, length = 8)
Did you mean to add this?
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.
Yeah, it was that or a longer statement to disable the warning for just that line. This took fewer keypresses, and won't complicate any future efforts to go over all the warnings we've disabled.
bin/NativeTests/UnicodeTextTests.cpp
Outdated
@@ -4,6 +4,10 @@ | |||
//------------------------------------------------------------------------------------------------------- | |||
|
|||
#include "stdafx.h" | |||
#pragma warning(disable:26434) |
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.
comments about what these warnings are? (not blocking PR)
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.
Sure, I'll add that in the next change.
lib/Backend/Lower.cpp
Outdated
@@ -21156,8 +21156,12 @@ Lowerer::GenerateArgOutForStackArgs(IR::Instr* callInstr, IR::Instr* stackArgsIn | |||
|
|||
|
|||
#if defined(_M_IX86) | |||
Assert(false); | |||
#endif | |||
// We get a compilation error on x86 due to assiging a negative to a uint |
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.
nit: assiging -> assigning
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.
Added in the next change.
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.
…analysis Merge pull request #5272 from Penguinwizzard:dev15_prefast_fixes This is one of the things that was preventing us from moving our jenkins CI to dev15.
…by Dev15 code analysis Merge pull request #5272 from Penguinwizzard:dev15_prefast_fixes This is one of the things that was preventing us from moving our jenkins CI to dev15.
This is one of the things that was preventing us from moving our jenkins CI to dev15.