// Copyright 2017 The Crashpad Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "util/misc/reinterpret_bytes.h" #include #include #include "base/logging.h" namespace crashpad { namespace internal { bool ReinterpretBytesImpl(const char* data, size_t data_size, char* dest, size_t dest_size) { // Verify that any unused bytes from data are zero. // The unused bytes are at the start of the data buffer for big-endian and the // end of the buffer for little-endian. if (dest_size < data_size) { auto extra_bytes = data; #if defined(ARCH_CPU_LITTLE_ENDIAN) extra_bytes += dest_size; #endif // ARCH_CPU_LITTLE_ENDIAN uint64_t zero = 0; size_t extra_bytes_size = data_size - dest_size; while (extra_bytes_size > 0) { size_t to_check = std::min(extra_bytes_size, sizeof(zero)); if (memcmp(extra_bytes, &zero, to_check) != 0) { LOG(ERROR) << "information loss"; return false; } extra_bytes += to_check; extra_bytes_size -= to_check; } } // Zero out the destination, in case it is larger than data. memset(dest, 0, dest_size); #if defined(ARCH_CPU_LITTLE_ENDIAN) // Copy a prefix of data to a prefix of dest for little-endian memcpy(dest, data, std::min(dest_size, data_size)); #else // or the suffix of data to the suffix of dest for big-endian if (data_size >= dest_size) { memcpy(dest, data + data_size - dest_size, dest_size); } else { memcpy(dest + dest_size - data_size, data, data_size); } #endif // ARCH_CPU_LITTLE_ENDIAN return true; } } // namespace internal } // namespace crashpad