Skip to content
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

[BUG] reinterpret_cast is misused in many places in cuIO #6029

Open
vuule opened this issue Aug 18, 2020 · 10 comments
Open

[BUG] reinterpret_cast is misused in many places in cuIO #6029

vuule opened this issue Aug 18, 2020 · 10 comments

Comments

@vuule
Copy link
Collaborator

@vuule vuule commented Aug 18, 2020

There are (at least) two ways in which the reinterpret_cast is misused:

  1. Used instead of static_cast:
    dataptr = reinterpret_cast<uint8_t *>(schema[i].dataptr);

    static cast should be used to cast from void*.
  2. The use causes undefined behavior:
    reinterpret_cast<int32_t *>(dataptr)[row] = static_cast<int32_t>(v);

    reinterpret_cast<nvstrdesc_s *>(dataptr)[row].ptr = ptr;
    reinterpret_cast<nvstrdesc_s *>(dataptr)[row].count = count;

    These uses break the type aliasing rules as they cast between pointers to types that are not similar.

Proposed solution:

  • Use static_cast where appropriate.
  • Buffers whose data type is not known at compile time (input/output buffers usually) should be of type void* instead of uint8_t*, as they commonly are now.
    • Addition of a hostdevice_buffer type might be beneficial here.
  • Where the options above are not applicable, use std::memcpy instead of the cast.

TODO list of components:

  • Avro
  • Compression
  • CSV
  • ORC
  • Parquet
  • Stats
  • Utilities
@OlivierNV
Copy link
Contributor

@OlivierNV OlivierNV commented Aug 25, 2020

omg

@harrism harrism added this to Issue-Needs prioritizing in v0.16 Release via automation Sep 9, 2020
@lamarrr
Copy link
Contributor

@lamarrr lamarrr commented Sep 21, 2020

For the second one, since it was stated that it represents the int type and we are converting between integral types and the converted-to type (int32) has the appropriate alignment, it's safe and not type-aliasing.

This is the case where:

int32_t data[5] = {};
schemadesc_s schema;
schema.data = reintepret_cast<void*>(data);
schema.type = type_int32;

// in the function context
auto dataptr = reinterpret_cast<uint8_t*>(schema.data);
reinterpret_cast<int32_t *>(dataptr)[row] = static_cast<int32_t>(v); 

converting from T* -> void* -> U* -> T* is not type aliasing, since it wasn't dereferenced in the U* state, only when it was converted back to T*.
But it'd be worth using void* instead of uint8_t*.

@jrhemstad
Copy link
Contributor

@jrhemstad jrhemstad commented Sep 21, 2020

But it'd be worth using void* instead of uint8_t*.

Agreed. If it was left as void* then static_cast could be used and it would look less circumspect.

@lamarrr
Copy link
Contributor

@lamarrr lamarrr commented Sep 21, 2020

@jrhemstad @vuule
I've made the changes in #6285. I also noticed and fixed the use of implicit pointer-to-bool conversions which is undefined behaviour.

@lamarrr
Copy link
Contributor

@lamarrr lamarrr commented Sep 25, 2020

@vuule the changes have been merged, do let me know if you need any additional changes to be made

@vuule
Copy link
Collaborator Author

@vuule vuule commented Sep 26, 2020

Hi @lamarrr , there are actually many other places in cudf::io where reinterpret_cast use is problematic. I only listed a couple of examples.
If you want to further help with this (and you are more than welcome), you can look for reinterpret_cast calls in cudf::io that cast between pointer types.

@vuule
Copy link
Collaborator Author

@vuule vuule commented Sep 26, 2020

Added the list of components so we can track progress more easily (since not all reinterpret_cast calls are a part of this issue).
JSON code does not seem to have any UB uses, so I did not include it in the list.

@lamarrr
Copy link
Contributor

@lamarrr lamarrr commented Sep 30, 2020

Hi @lamarrr , there are actually many other places in cudf::io where reinterpret_cast use is problematic. I only listed a couple of examples.
If you want to further help with this (and you are more than welcome), you can look for reinterpret_cast calls in cudf::io that cast between pointer types.

Yeah, sure! I'll try to help with some cleanups and push them within a day or two.
I also noted some c-style pointer casts which are essentially a combination of const_casts, reinterpret_cast, static_cast, and volatile casts. Essentially, possibly being a reinterpret_cast means it's just as dangerous as reinterpret_cast.

@harrism harrism moved this from Issue-Needs prioritizing to Issue-P1 in v0.16 Release Oct 2, 2020
@cwharris cwharris assigned cwharris and unassigned mt-jones Oct 2, 2020
@harrism harrism added this to Issue-Needs prioritizing in v0.17 Release via automation Oct 11, 2020
@harrism harrism removed this from Issue-P1 in v0.16 Release Oct 11, 2020
@vuule vuule self-assigned this Oct 12, 2020
@vuule vuule closed this in #6386 Oct 13, 2020
v0.17 Release automation moved this from Issue-Needs prioritizing to Done Oct 13, 2020
@vuule
Copy link
Collaborator Author

@vuule vuule commented Oct 13, 2020

Missed the "closes" tag in #6386. Reopening.

@vuule
Copy link
Collaborator Author

@vuule vuule commented Oct 13, 2020

Please note that most code that cooperatively loads structs uses reinterpret_cast to cast between pointer types. These instances will be addressed as part of #6236, please skip such cases when working on this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
v0.17 Release
  
Issue-P1
Linked pull requests

Successfully merging a pull request may close this issue.

6 participants
You can’t perform that action at this time.