blob: 65ec33f348ec62598a104f62991e4545c9d9c4c3 [file] [log] [blame]
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// 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 <string.h>
#include <algorithm>
#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