reinterpret_bytes.cc 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright 2017 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "util/misc/reinterpret_bytes.h"
  15. #include <string.h>
  16. #include <algorithm>
  17. #include "base/logging.h"
  18. namespace crashpad {
  19. namespace internal {
  20. bool ReinterpretBytesImpl(const char* data,
  21. size_t data_size,
  22. char* dest,
  23. size_t dest_size) {
  24. // Verify that any unused bytes from data are zero.
  25. // The unused bytes are at the start of the data buffer for big-endian and the
  26. // end of the buffer for little-endian.
  27. if (dest_size < data_size) {
  28. auto extra_bytes = data;
  29. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  30. extra_bytes += dest_size;
  31. #endif // ARCH_CPU_LITTLE_ENDIAN
  32. uint64_t zero = 0;
  33. size_t extra_bytes_size = data_size - dest_size;
  34. while (extra_bytes_size > 0) {
  35. size_t to_check = std::min(extra_bytes_size, sizeof(zero));
  36. if (memcmp(extra_bytes, &zero, to_check) != 0) {
  37. LOG(ERROR) << "information loss";
  38. return false;
  39. }
  40. extra_bytes += to_check;
  41. extra_bytes_size -= to_check;
  42. }
  43. }
  44. // Zero out the destination, in case it is larger than data.
  45. memset(dest, 0, dest_size);
  46. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  47. // Copy a prefix of data to a prefix of dest for little-endian
  48. memcpy(dest, data, std::min(dest_size, data_size));
  49. #else
  50. // or the suffix of data to the suffix of dest for big-endian
  51. if (data_size >= dest_size) {
  52. memcpy(dest, data + data_size - dest_size, dest_size);
  53. } else {
  54. memcpy(dest + dest_size - data_size, data, data_size);
  55. }
  56. #endif // ARCH_CPU_LITTLE_ENDIAN
  57. return true;
  58. }
  59. } // namespace internal
  60. } // namespace crashpad