WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
204411
[JSCOnly] 32-bits warning on memset of JSValue
https://bugs.webkit.org/show_bug.cgi?id=204411
Summary
[JSCOnly] 32-bits warning on memset of JSValue
Caio Lima
Reported
2019-11-20 07:33:15 PST
This is current warning: ``` [42/54] Building CXX object Source/JavaScriptCore/CMakeFiles/JavaScriptCore.dir/__/__/DerivedSources/JavaScriptCore/unified-sources/UnifiedSource-f2e18ffc-17.cpp.o In file included from ../../Source/JavaScriptCore/heap/Heap.h:31, from ../../Source/JavaScriptCore/heap/DeferGC.h:29, from ../../Source/JavaScriptCore/runtime/ConcurrentJSLock.h:28, from ../../Source/JavaScriptCore/runtime/VM.h:34, from ../../Source/JavaScriptCore/interpreter/CallFrame.h:30, from ../../Source/JavaScriptCore/runtime/ArgList.h:24, from ../../Source/JavaScriptCore/runtime/JSArray.h:23, from ../../Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h:29, from ../../Source/JavaScriptCore/runtime/JSGlobalObject.h:24, from ../../Source/JavaScriptCore/runtime/JSFixedArray.h:28, from ../../Source/JavaScriptCore/runtime/JSFixedArray.cpp:27, from DerivedSources/JavaScriptCore/unified-sources/UnifiedSource-f2e18ffc-17.cpp:1: ../../Source/JavaScriptCore/heap/GCMemoryOperations.h: In instantiation of ‘void JSC::gcSafeZeroMemory(T*, size_t) [with T = JSC::JSValue; size_t = unsigned int]’: ../../Source/JavaScriptCore/runtime/RegExpMatchesArray.h:97:123: required from here ../../Source/JavaScriptCore/heap/GCMemoryOperations.h:307:11: warning: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘class JSC::JSValue’; use assignment or value-initialization instead [-Wclass-memaccess] memset(dst, 0, bytes); ~~~~~~^~~~~~~~~~~~~~~ In file included from ../../Source/JavaScriptCore/bytecode/SpeculatedType.h:32, from ../../Source/JavaScriptCore/runtime/IndexingType.h:28, from ../../Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h:28, from ../../Source/JavaScriptCore/runtime/JSGlobalObject.h:24, from ../../Source/JavaScriptCore/runtime/JSFixedArray.h:28, from ../../Source/JavaScriptCore/runtime/JSFixedArray.cpp:27, from DerivedSources/JavaScriptCore/unified-sources/UnifiedSource-f2e18ffc-17.cpp:1: ../../Source/JavaScriptCore/runtime/JSCJSValue.h:136:7: note: ‘class JSC::JSValue’ declared here class JSValue { ^~~~~~~ ```
Attachments
Patch
(1.41 KB, patch)
2019-11-22 01:52 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(1.44 KB, patch)
2019-11-22 06:33 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(2.07 KB, patch)
2019-11-22 09:51 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(2.05 KB, patch)
2019-12-02 00:28 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(2.81 KB, patch)
2019-12-06 04:54 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(3.10 KB, patch)
2019-12-06 04:59 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(2.83 KB, patch)
2019-12-09 03:34 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(1.45 KB, patch)
2020-03-04 03:34 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Patch
(1.46 KB, patch)
2020-03-04 23:59 PST
,
Paulo Matos
no flags
Details
Formatted Diff
Diff
Show Obsolete
(8)
View All
Add attachment
proposed patch, testcase, etc.
Paulo Matos
Comment 1
2019-11-22 01:52:21 PST
Created
attachment 384132
[details]
Patch
Paulo Matos
Comment 2
2019-11-22 02:30:44 PST
Uploaded patch to the wrong bug. :( Apologies.
Paulo Matos
Comment 3
2019-11-22 06:33:24 PST
Created
attachment 384148
[details]
Patch
Paulo Matos
Comment 4
2019-11-22 06:34:40 PST
Hopefully it is now the right patch. :-)
Caio Lima
Comment 5
2019-11-22 06:42:33 PST
Comment on
attachment 384148
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384148&action=review
> Source/JavaScriptCore/heap/GCMemoryOperations.h:309 > + bitwise_cast<volatile uint32_t*>(dst)[i] = 0;
What about casting `dst` to `void*`? The we would have `memset(bitwise_cast<void*>(dst), 0, bytes);`.
Paulo Matos
Comment 6
2019-11-22 06:48:28 PST
(In reply to Caio Lima from
comment #5
)
> Comment on
attachment 384148
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=384148&action=review
> > > Source/JavaScriptCore/heap/GCMemoryOperations.h:309 > > + bitwise_cast<volatile uint32_t*>(dst)[i] = 0; > > What about casting `dst` to `void*`? The we would have > `memset(bitwise_cast<void*>(dst), 0, bytes);`.
Actually using memset here is always bad because GCC can potentially optimize it away. Instead, we could potentially use std::fill but I thought it would fit better with the code to do it as x86_64 does it. At the same time, I am still looking at this and wondering if this is correct, because although I haven't seen test failures yet, I think the JSVALUE in 32bits are two 64bits, in which case, we might need to double the count.
Caio Lima
Comment 7
2019-11-22 07:03:31 PST
Comment on
attachment 384148
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384148&action=review
>>> Source/JavaScriptCore/heap/GCMemoryOperations.h:309 >>> + bitwise_cast<volatile uint32_t*>(dst)[i] = 0; >> >> What about casting `dst` to `void*`? The we would have `memset(bitwise_cast<void*>(dst), 0, bytes);`. > > Actually using memset here is always bad because GCC can potentially optimize it away. Instead, we could potentially use std::fill but I thought it would fit better with the code to do it as x86_64 does it. > > At the same time, I am still looking at this and wondering if this is correct, because although I haven't seen test failures yet, I think the JSVALUE in 32bits are two 64bits, in which case, we might need to double the count.
sizeof(JSValue) on 32-bits is also 8 bytes (
https://github.com/caiolima/webkit/blob/master/Source/JavaScriptCore/runtime/JSCJSValue.h#L344
). The difference from JSValue64 is the enconding of values. On 32-bits we use high 32-bits as the tag and the other 32-bits as the payload. One thing that I'm missing here is what's bad about GCC optimizing `memset`? Is it possible to remove this code with DCE or something like that?
Paulo Matos
Comment 8
2019-11-22 08:28:16 PST
(In reply to Caio Lima from
comment #7
)
> Comment on
attachment 384148
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=384148&action=review
> > >>> Source/JavaScriptCore/heap/GCMemoryOperations.h:309 > >>> + bitwise_cast<volatile uint32_t*>(dst)[i] = 0; > >> > >> What about casting `dst` to `void*`? The we would have `memset(bitwise_cast<void*>(dst), 0, bytes);`. > > > > Actually using memset here is always bad because GCC can potentially optimize it away. Instead, we could potentially use std::fill but I thought it would fit better with the code to do it as x86_64 does it. > > > > At the same time, I am still looking at this and wondering if this is correct, because although I haven't seen test failures yet, I think the JSVALUE in 32bits are two 64bits, in which case, we might need to double the count. > > sizeof(JSValue) on 32-bits is also 8 bytes > (
https://github.com/caiolima/webkit/blob/master/Source/JavaScriptCore/
> runtime/JSCJSValue.h#L344). The difference from JSValue64 is the enconding > of values. On 32-bits we use high 32-bits as the tag and the other 32-bits > as the payload.
I thought that could be the case, which is why I mentioned my patch is probably broken even though no tests were seen to fail.
> One thing that I'm missing here is what's bad about GCC > optimizing `memset`? Is it possible to remove this code with DCE or > something like that?
If gcc optimizes memset away, then it won't zero the memory. And this is a security issue. Yes, DCE can in GCC eliminate the memset.
Paulo Matos
Comment 9
2019-11-22 09:51:19 PST
Created
attachment 384163
[details]
Patch
Mark Lam
Comment 10
2019-11-22 10:13:33 PST
Comment on
attachment 384163
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384163&action=review
r=me with fix.
> Source/JavaScriptCore/heap/GCMemoryOperations.h:256 > + RELEASE_ASSERT(bytes % 8 == 0);
Please remove this RELEASE_ASSERT. It's not necessarily free and it's redundant with the one at the top of gcSafeZeroMemory(). You can make it a debug ASSERT.
Saam Barati
Comment 11
2019-11-30 16:41:22 PST
Comment on
attachment 384163
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384163&action=review
> Source/JavaScriptCore/heap/GCMemoryOperations.h:-307 > - memset(dst, 0, bytes);
Why are we no longer calling memset? That’s faster than the loop. Maybe just silence the warning instead?
Paulo Matos
Comment 12
2019-12-01 23:38:38 PST
(In reply to Saam Barati from
comment #11
)
> Comment on
attachment 384163
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=384163&action=review
> > > Source/JavaScriptCore/heap/GCMemoryOperations.h:-307 > > - memset(dst, 0, bytes); > > Why are we no longer calling memset? That’s faster than the loop. Maybe just > silence the warning instead?
There's a possibility that the compiler might remove the memset call and the zero'ing of memory won't happen.
Paulo Matos
Comment 13
2019-12-02 00:28:46 PST
Created
attachment 384596
[details]
Patch
Mark Lam
Comment 14
2019-12-02 09:17:04 PST
Comment on
attachment 384596
[details]
Patch Wasn't this already landed previously? Was it rolled out? If so, why, and why is it ok to land again?
Mark Lam
Comment 15
2019-12-02 09:17:56 PST
(In reply to Mark Lam from
comment #14
)
> Comment on
attachment 384596
[details]
> Patch > > Wasn't this already landed previously? Was it rolled out? If so, why, and > why is it ok to land again?
OK, looks like it was never landed.
Mark Lam
Comment 16
2019-12-02 09:20:08 PST
Comment on
attachment 384596
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384596&action=review
> Source/JavaScriptCore/ChangeLog:9 > + Implemented alternative to memset, and refactored solutions. > + Fixes warning on 32bit builds.
It's probably worth adding a comment here that a compiler may choose to optimize away the memset (given Saam's question), or elaborate on what the warning is if it is related.
Mark Lam
Comment 17
2019-12-02 09:25:50 PST
Comment on
attachment 384596
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384596&action=review
> Source/JavaScriptCore/heap/GCMemoryOperations.h:311 > bitwise_cast<volatile uint64_t*>(dst)[i] = 0;
Please also change this #else case to use gcSafeZeroMemoryHelper(dst, bytes) since it is identical code.
Paulo Matos
Comment 18
2019-12-06 04:54:28 PST
Created
attachment 385003
[details]
Patch
Paulo Matos
Comment 19
2019-12-06 04:59:06 PST
Created
attachment 385004
[details]
Patch
Paulo Matos
Comment 20
2019-12-06 04:59:49 PST
(In reply to Mark Lam from
comment #17
)
> Comment on
attachment 384596
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=384596&action=review
> > > Source/JavaScriptCore/heap/GCMemoryOperations.h:311 > > bitwise_cast<volatile uint64_t*>(dst)[i] = 0; > > Please also change this #else case to use gcSafeZeroMemoryHelper(dst, bytes) > since it is identical code.
Mark, sorry for the delay on this. I hope all concerns have now been taken care of.
Darin Adler
Comment 21
2019-12-06 12:32:38 PST
Comment on
attachment 385004
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=385004&action=review
> Source/JavaScriptCore/heap/GCMemoryOperations.h:277 > + return;
Seems that using unconditional return like this could eventually lead to unreachable code warnings. Can we use #else instead of return?
Paulo Matos
Comment 22
2019-12-09 03:34:19 PST
Created
attachment 385142
[details]
Patch
Paulo Matos
Comment 23
2019-12-09 05:44:33 PST
(In reply to Darin Adler from
comment #21
)
> Comment on
attachment 385004
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=385004&action=review
> > > Source/JavaScriptCore/heap/GCMemoryOperations.h:277 > > + return; > > Seems that using unconditional return like this could eventually lead to > unreachable code warnings. Can we use #else instead of return?
Right - well thought out. I have updated the patch.
Saam Barati
Comment 24
2019-12-12 12:02:44 PST
Comment on
attachment 384163
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384163&action=review
>>> Source/JavaScriptCore/heap/GCMemoryOperations.h:-307 >>> - memset(dst, 0, bytes); >> >> Why are we no longer calling memset? That’s faster than the loop. Maybe just silence the warning instead? > > There's a possibility that the compiler might remove the memset call and the zero'ing of memory won't happen.
How? Why could the compiler delete memset?
Paulo Matos
Comment 25
2020-01-06 02:47:19 PST
(In reply to Saam Barati from
comment #24
)
> Comment on
attachment 384163
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=384163&action=review
> > >>> Source/JavaScriptCore/heap/GCMemoryOperations.h:-307 > >>> - memset(dst, 0, bytes); > >> > >> Why are we no longer calling memset? That’s faster than the loop. Maybe just silence the warning instead? > > > > There's a possibility that the compiler might remove the memset call and the zero'ing of memory won't happen. > > How? Why could the compiler delete memset?
Saam, sorry for the delay. See Notes in
https://en.cppreference.com/w/c/string/byte/memset
: Quote: - memset may be optimized away (under the as-if rules) if the object modified by this function is not accessed again for the rest of its lifetime (e.g. gcc bug 8537). For that reason, this function cannot be used to scrub memory (e.g. to fill an array that stored a password with zeroes). This optimization is prohibited for memset_s: it is guaranteed to perform the memory write. Third-party solutions for that include FreeBSD explicit_bzero or Microsoft SecureZeroMemory. - memset should not be used for safe zero'ing, which is why memset_s exists. I have found this explanation as well:
https://www.cryptologie.net/article/419/zeroing-memory-compiler-optimizations-and-memset_s/
Paulo Matos
Comment 26
2020-01-08 07:16:44 PST
ping for r+/cq+ if there are no further issues?
Paulo Matos
Comment 27
2020-03-02 06:03:35 PST
ping?
Yusuke Suzuki
Comment 28
2020-03-02 11:10:50 PST
Comment on
attachment 384163
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=384163&action=review
>>>>> Source/JavaScriptCore/heap/GCMemoryOperations.h:-307 >>>>> - memset(dst, 0, bytes); >>>> >>>> Why are we no longer calling memset? That’s faster than the loop. Maybe just silence the warning instead? >>> >>> There's a possibility that the compiler might remove the memset call and the zero'ing of memory won't happen. >> >> How? Why could the compiler delete memset? > > Saam, sorry for the delay. > See Notes in
https://en.cppreference.com/w/c/string/byte/memset
: > Quote: > - > memset may be optimized away (under the as-if rules) if the object modified by this function is not accessed again for the rest of its lifetime (e.g. gcc bug 8537). For that reason, this function cannot be used to scrub memory (e.g. to fill an array that stored a password with zeroes). This optimization is prohibited for memset_s: it is guaranteed to perform the memory write. Third-party solutions for that include FreeBSD explicit_bzero or Microsoft SecureZeroMemory. > - > > memset should not be used for safe zero'ing, which is why memset_s exists. > I have found this explanation as well: >
https://www.cryptologie.net/article/419/zeroing-memory-compiler-optimizations-and-memset_s/
I think this "memset" issue is typically tight to the security issues. And in this case, this is unrelated. The issue happens when zeroing the value which can contain security-token etc. But it is not scratched (
https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf
). In this case, I think it does not matter. We are not using memset to the security related thing, it is used for GC memory's clearing. And if it is read by GC, which means it is escaped from the allocation, so GCC never removes this memset. Is my understanding correct?
Paulo Matos
Comment 29
2020-03-04 02:45:11 PST
(In reply to Yusuke Suzuki from
comment #28
)
> > I think this "memset" issue is typically tight to the security issues. And > in this case, this is unrelated. > The issue happens when zeroing the value which can contain security-token > etc. But it is not scratched > (
https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang
. > pdf). > In this case, I think it does not matter. We are not using memset to the > security related thing, it is used for GC memory's clearing. And if it is > read by GC, which means it is escaped from the allocation, so GCC never > removes this memset. > Is my understanding correct?
Hi Yusuke, Thanks for the comments on this. I think you are correct. I was looking at the code and at how DSE deals with this in GCC8 and it looks like it won't be removed. Unsure exactly why but my guess it that GCC might not be able to prove that the address is not read or because it's inside a template. Usually GCC can be quite aggressive in removing stores like this in C code. For example:
https://godbolt.org/z/TYQeqx
But it is certainly true that this is not a security concern for us and as far as I understand this code (although first time looking at GC), it wouldn't be a problem if indeed GCC removes the store. I will propose a simpler patch where I cast the dst pointer to a (char *) to avoid the error of memsetting a non-POD type.
Paulo Matos
Comment 30
2020-03-04 03:34:40 PST
Created
attachment 392401
[details]
Patch
Alex Christensen
Comment 31
2020-03-04 09:17:44 PST
Comment on
attachment 392401
[details]
Patch We prefer C++ style casts. reinterpret_cast<char*>(dst)
Yusuke Suzuki
Comment 32
2020-03-04 13:13:06 PST
r=me too, and agree with Alex. Let's use C++ style cast.
Paulo Matos
Comment 33
2020-03-04 23:59:01 PST
Created
attachment 392541
[details]
Patch
Paulo Matos
Comment 34
2020-03-04 23:59:35 PST
(In reply to Yusuke Suzuki from
comment #32
)
> r=me too, and agree with Alex. Let's use C++ style cast.
Thanks. Sure
Mark Lam
Comment 35
2020-03-05 00:07:20 PST
Comment on
attachment 392541
[details]
Patch r=me
WebKit Commit Bot
Comment 36
2020-03-05 00:54:54 PST
Comment on
attachment 392541
[details]
Patch Clearing flags on attachment: 392541 Committed
r257908
: <
https://trac.webkit.org/changeset/257908
>
WebKit Commit Bot
Comment 37
2020-03-05 00:54:56 PST
All reviewed patches have been landed. Closing bug.
Radar WebKit Bug Importer
Comment 38
2020-03-05 00:55:20 PST
<
rdar://problem/60075573
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug