-
Notifications
You must be signed in to change notification settings - Fork 62
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
Fix some sources of undefined behavior #1171
Conversation
@@ -1510,7 +1510,7 @@ float VectorDistanceSquared( vec3_t v1, vec3_t v2 ) | |||
// *INDENT-OFF* | |||
void MatrixIdentity( matrix_t m ) | |||
{ | |||
memcpy( m, matrixIdentity, sizeof( matrix_t ) ); | |||
MatrixCopy( matrixIdentity, m ); |
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.
One thing I like with memcpy
is that compilers usually know the best way to copy and use intrinsics as much as possible, usually even in debug mode, while you need some levels of compiler optimizations to get MatrixCopy
vectorized by the compiler.
I wonder if we can have a custom memcpy
with an assert it's not null (for non-user provided data), and one with a check otherwise, when std::copy_n
is not available.
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 UB problem of memcpy
is very annoying because memcpy
is very efficient and is assumed to do the best for the task…
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.
Well, MatrixCopy still does memcpy :) This case is not one of the risky ones as the array is fixed-length. Here I'm really just trying to reduce the number of times memcpy
appears in the source.
Also std::copy
and friends are expected to shell out to memcpy when applicable (nonzero length, struct is POD or whatever)
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.
Well, MatrixCopy still does memcpy :)
Ahah, yes, that's true for this one, I'm even the one who did it: d8089d6 😄️
@@ -54,15 +54,15 @@ int trap_CM_MarkFragments( int numPoints, const vec3_t *points, const vec3_t pro | |||
|
|||
std::vector<std::array<float, 3>> mypoints(numPoints); | |||
std::array<float, 3> myproj; | |||
memcpy((float*)mypoints.data(), points, sizeof(float) * 3 * numPoints); | |||
memcpy(mypoints.data(), points, sizeof(float) * 3 * numPoints); |
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 one may be a good candidate for a custom memcpy
with a check if there is no alternative to memcpy
.
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.
Right. In this case the types are incompatible according to C++ rules, but we know the layout is the same.
Can Quoting https://en.cppreference.com/w/c/string/byte/memcpy :
|
d97dd30
to
9591fba
Compare
I don't think so. The advantage would be that calling it with a null pointer is now a defined behavior: it definitely crashes. But this is outweighed by the negatives. Calculating the destination writable size seems like a pain in the ass and could introduce new crashes because we did it wrong. Also I imagine that compilers would not be able to inline this, so we would lose efficiency. |
memcpying into a vector can cause UB if the size is 0. In most cases, ths more efficient iterator-based constructor can be used. Fixes Unvanquished/Unvanquished#2682 (the underlying cause).
Motivated by DaemonEngine#839 (comment) At least 2 places looked definitely buggy (i.e. can pass null to memcpy): - StripColors (one of the StripColors variants was deleted due to the bug but there is another!) - Util::Reader::ReadData (when reading an empty vector)
Doing (&red)[2] via ToArray() is UB
9591fba
to
73e08a2
Compare
Color
to avoid UB array indexing style