mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 02:25:52 +00:00
The current implementation of rngfill is prone to false warnings from GCC about array bounds violations. Looking at the code, the implementation naively manipulates both the bytes count and the buffer pointer directly to ensure the trailing memcpy doesn't overrun the buffer. As expressed, there is a data dependency on both fields between loop iterations. Now, ideally, an optimizing compiler would realize that these dependencies were unnecessary and end up restructuring its intermediate representation into a functionally equivalent form with them absent. However, the point at which this occurs may be disjoint from when warning analyses are performed, potentially rendering them more difficult to determine precisely. In addition, it may also consume a portion of the budget the optimizer has allocated to attempting to improve a translation unit's performance. Given this is a function template which requires context-sensitive instantiation, this code would be more prone than most to being inlined, with a decrease in optimization budget corresponding to the effort the optimizer has already expended, having already optimized one or more calling functions. Thus, the scope for impacting the the ultimate quality of the code generated is elevated. For this change, we rearrange things so that the location and contents of each memcpy can be computed independently, relying on a simple loop iteration counter as the only changing input between iterations.
75 lines
2.5 KiB
C++
75 lines
2.5 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#ifndef BEAST_RANDOM_RNGFILL_H_INCLUDED
|
|
#define BEAST_RANDOM_RNGFILL_H_INCLUDED
|
|
|
|
#include <xrpl/beast/utility/instrumentation.h>
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <type_traits>
|
|
|
|
namespace beast {
|
|
|
|
template <class Generator>
|
|
void
|
|
rngfill(void* const buffer, std::size_t const bytes, Generator& g)
|
|
{
|
|
using result_type = typename Generator::result_type;
|
|
constexpr std::size_t result_size = sizeof(result_type);
|
|
|
|
std::uint8_t* const buffer_start = static_cast<std::uint8_t*>(buffer);
|
|
std::size_t const complete_iterations = bytes / result_size;
|
|
std::size_t const bytes_remaining = bytes % result_size;
|
|
|
|
for (std::size_t count = 0; count < complete_iterations; ++count)
|
|
{
|
|
result_type const v = g();
|
|
std::size_t const offset = count * result_size;
|
|
std::memcpy(buffer_start + offset, &v, result_size);
|
|
}
|
|
|
|
if (bytes_remaining > 0)
|
|
{
|
|
result_type const v = g();
|
|
std::size_t const offset = complete_iterations * result_size;
|
|
std::memcpy(buffer_start + offset, &v, bytes_remaining);
|
|
}
|
|
}
|
|
|
|
template <
|
|
class Generator,
|
|
std::size_t N,
|
|
class = std::enable_if_t<N % sizeof(typename Generator::result_type) == 0>>
|
|
void
|
|
rngfill(std::array<std::uint8_t, N>& a, Generator& g)
|
|
{
|
|
using result_type = typename Generator::result_type;
|
|
auto i = N / sizeof(result_type);
|
|
result_type* p = reinterpret_cast<result_type*>(a.data());
|
|
while (i--)
|
|
*p++ = g();
|
|
}
|
|
|
|
} // namespace beast
|
|
|
|
#endif
|