<commit_before>// RUN: %clangxx_asan -O0 %s -o %t
// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL

#include <stdio.h>
#include <stdlib.h>

int main() {
  void *p = aligned_alloc(17, 100);
  // CHECK: ERROR: AddressSanitizer: invalid allocation alignment: 17
  // CHECK: {{#0 0x.* in .*aligned_alloc}}
  // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]]
  // CHECK: SUMMARY: AddressSanitizer: invalid-allocation-alignment

  printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
  // CHECK-NULL: pointer after failed aligned_alloc: 0

  return 0;
}
<commit_msg>[ASan] Add aligned_alloc declaration to aligned_alloc-alignment.cc test.<commit_after>// RUN: %clangxx_asan -O0 %s -o %t
// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL

#include <stdio.h>
#include <stdlib.h>

extern void *aligned_alloc (size_t alignment, size_t size);

int main() {
  void *p = aligned_alloc(17, 100);
  // CHECK: ERROR: AddressSanitizer: invalid allocation alignment: 17
  // CHECK: {{#0 0x.* in .*aligned_alloc}}
  // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]]
  // CHECK: SUMMARY: AddressSanitizer: invalid-allocation-alignment

  printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
  // CHECK-NULL: pointer after failed aligned_alloc: 0

  return 0;
}
<|endoftext|>


<commit_before>// 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 <string>
#include <utility>

#include <boost/functional/hash.hpp>

#include <stout/hashset.hpp>

#include <gtest/gtest.h>

#include <gmock/gmock.h>

using std::string;

TEST(HashsetTest, InitializerList)
{
  hashset<string> set{"hello"};
  EXPECT_EQ(1u, set.size());

  EXPECT_TRUE((hashset<int>{}.empty()));

  hashset<int> set1{1, 3, 5, 7, 11};
  EXPECT_EQ(5u, set1.size());
  EXPECT_TRUE(set1.contains(1));
  EXPECT_TRUE(set1.contains(3));
  EXPECT_TRUE(set1.contains(5));
  EXPECT_TRUE(set1.contains(7));
  EXPECT_TRUE(set1.contains(11));

  EXPECT_FALSE(set1.contains(2));
}

TEST(HashsetTest, FromStdSet)
{
  std::set<int> set1{1, 3, 5, 7};

  hashset<int> set2(set1);

  EXPECT_EQ(set1.size(), set2.size());
  EXPECT_EQ(4u, set2.size());

  foreach (const auto set1_entry, set1) {
    EXPECT_TRUE(set2.contains(set1_entry));
  }
}

TEST(HashsetTest, FromRValueStdSet)
{
  std::set<int> set1{1, 3};

  hashset<int> set2(std::move(set1));

  EXPECT_EQ(2u, set2.size());

  EXPECT_TRUE(set2.contains(1));
  EXPECT_TRUE(set2.contains(3));

  EXPECT_FALSE(set2.contains(2));
}

TEST(HashsetTest, CustomHashAndEqual)
{
  struct CaseInsensitiveHash
  {
    size_t operator()(const string& key) const
    {
      size_t seed = 0;
      foreach (const char c, key) {
        boost::hash_combine(seed, ::tolower(c));
      }
      return seed;
    }
  };

  struct CaseInsensitiveEqual
  {
    bool operator()(const string& left, const string& right) const
    {
      if (left.size() != right.size()) {
        return false;
      }
      for (size_t i = 0; i < left.size(); ++i) {
        if (::tolower(left[i]) != ::tolower(right[i])) {
          return false;
        }
      }
      return true;
    }
  };

  hashset<string, CaseInsensitiveHash, CaseInsensitiveEqual> set;

  set.insert("abc");
  set.insert("def");
  EXPECT_TRUE(set.contains("Abc"));
  EXPECT_TRUE(set.contains("dEf"));

  EXPECT_EQ(2u, set.size());
  set.insert("Abc");
  set.insert("DEF");
  EXPECT_EQ(2u, set.size());
  EXPECT_TRUE(set.contains("abc"));
  EXPECT_TRUE(set.contains("def"));
}

TEST(HashsetTest, Insert)
{
  hashset<string> hs1;
  hs1.insert(string("HS1"));
  hs1.insert(string("HS3"));

  hashset<string> hs2;
  hs2.insert(string("HS2"));

  hs1 = hs2;
  ASSERT_EQ(1u, hs1.size());
  ASSERT_TRUE(hs1.contains("HS2"));
  ASSERT_TRUE(hs1 == hs2);
}

TEST(HashsetTest, Union)
{
  hashset<int> hs1;
  hs1.insert(1);
  hs1.insert(2);
  hs1.insert(3);

  hashset<int> hs2;
  hs2.insert(3);
  hs2.insert(4);
  hs2.insert(5);

  hashset<int> hs3 = hs1 | hs2;

  ASSERT_EQ(5u, hs3.size());
  ASSERT_TRUE(hs3.contains(1));
  ASSERT_TRUE(hs3.contains(2));
  ASSERT_TRUE(hs3.contains(3));
  ASSERT_TRUE(hs3.contains(4));
  ASSERT_TRUE(hs3.contains(5));

  hashset<int> hs4 = hs1;
  hs4 |= hs2;

  ASSERT_EQ(hs3, hs4);
}
<commit_msg>Added test for difference operator of hashset.<commit_after>// 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 <string>
#include <utility>

#include <boost/functional/hash.hpp>

#include <stout/hashset.hpp>

#include <gtest/gtest.h>

#include <gmock/gmock.h>

using std::string;

TEST(HashsetTest, InitializerList)
{
  hashset<string> set{"hello"};
  EXPECT_EQ(1u, set.size());

  EXPECT_TRUE((hashset<int>{}.empty()));

  hashset<int> set1{1, 3, 5, 7, 11};
  EXPECT_EQ(5u, set1.size());
  EXPECT_TRUE(set1.contains(1));
  EXPECT_TRUE(set1.contains(3));
  EXPECT_TRUE(set1.contains(5));
  EXPECT_TRUE(set1.contains(7));
  EXPECT_TRUE(set1.contains(11));

  EXPECT_FALSE(set1.contains(2));
}

TEST(HashsetTest, FromStdSet)
{
  std::set<int> set1{1, 3, 5, 7};

  hashset<int> set2(set1);

  EXPECT_EQ(set1.size(), set2.size());
  EXPECT_EQ(4u, set2.size());

  foreach (const auto set1_entry, set1) {
    EXPECT_TRUE(set2.contains(set1_entry));
  }
}

TEST(HashsetTest, FromRValueStdSet)
{
  std::set<int> set1{1, 3};

  hashset<int> set2(std::move(set1));

  EXPECT_EQ(2u, set2.size());

  EXPECT_TRUE(set2.contains(1));
  EXPECT_TRUE(set2.contains(3));

  EXPECT_FALSE(set2.contains(2));
}

TEST(HashsetTest, CustomHashAndEqual)
{
  struct CaseInsensitiveHash
  {
    size_t operator()(const string& key) const
    {
      size_t seed = 0;
      foreach (const char c, key) {
        boost::hash_combine(seed, ::tolower(c));
      }
      return seed;
    }
  };

  struct CaseInsensitiveEqual
  {
    bool operator()(const string& left, const string& right) const
    {
      if (left.size() != right.size()) {
        return false;
      }
      for (size_t i = 0; i < left.size(); ++i) {
        if (::tolower(left[i]) != ::tolower(right[i])) {
          return false;
        }
      }
      return true;
    }
  };

  hashset<string, CaseInsensitiveHash, CaseInsensitiveEqual> set;

  set.insert("abc");
  set.insert("def");
  EXPECT_TRUE(set.contains("Abc"));
  EXPECT_TRUE(set.contains("dEf"));

  EXPECT_EQ(2u, set.size());
  set.insert("Abc");
  set.insert("DEF");
  EXPECT_EQ(2u, set.size());
  EXPECT_TRUE(set.contains("abc"));
  EXPECT_TRUE(set.contains("def"));
}

TEST(HashsetTest, Insert)
{
  hashset<string> hs1;
  hs1.insert(string("HS1"));
  hs1.insert(string("HS3"));

  hashset<string> hs2;
  hs2.insert(string("HS2"));

  hs1 = hs2;
  ASSERT_EQ(1u, hs1.size());
  ASSERT_TRUE(hs1.contains("HS2"));
  ASSERT_TRUE(hs1 == hs2);
}

TEST(HashsetTest, Union)
{
  hashset<int> hs1;
  hs1.insert(1);
  hs1.insert(2);
  hs1.insert(3);

  hashset<int> hs2;
  hs2.insert(3);
  hs2.insert(4);
  hs2.insert(5);

  hashset<int> hs3 = hs1 | hs2;

  ASSERT_EQ(5u, hs3.size());
  ASSERT_TRUE(hs3.contains(1));
  ASSERT_TRUE(hs3.contains(2));
  ASSERT_TRUE(hs3.contains(3));
  ASSERT_TRUE(hs3.contains(4));
  ASSERT_TRUE(hs3.contains(5));

  hashset<int> hs4 = hs1;
  hs4 |= hs2;

  ASSERT_EQ(hs3, hs4);
}

TEST(HashsetTest, Difference)
{
  hashset<int> hs1;
  hs1.insert(1);
  hs1.insert(2);
  hs1.insert(3);

  hashset<int> hs2;
  hs2.insert(3);
  hs2.insert(4);
  hs2.insert(5);

  hashset<int> hs3 = hs1 - hs2;

  ASSERT_EQ(2u, hs3.size());
  ASSERT_TRUE(hs3.contains(1));
  ASSERT_TRUE(hs3.contains(2));
  ASSERT_FALSE(hs3.contains(3));
  ASSERT_FALSE(hs3.contains(4));
  ASSERT_FALSE(hs3.contains(5));

  hashset<int> hs4 = hs1;
  hs4 -= hs2;

  ASSERT_EQ(hs3, hs4);
}
<|endoftext|>


<commit_before>// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t

long size() { return 294967296l; }

////////////////////////////////////////////////////////////////////////////////
/// Test cases correctly caught by bugprone-too-small-loop-variable.

void voidBadForLoop() {
  for (int i = 0; i < size(); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop2() {
  for (int i = 0; i < size() + 10; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop3() {
  for (int i = 0; i <= size() - 1; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop4() {
  for (int i = 0; size() > i; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop5() {
  for (int i = 0; size() - 1 >= i; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop6() {
  int i = 0;
  for (; i < size(); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidForLoopUnsignedBound() {
  unsigned size = 3147483647;
  for (int i = 0; i < size; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
  }
}

// The iteration's upper bound has a template dependent value.
template <long size>
void doSomething() {
  for (short i = 0; i < size; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

// The iteration's upper bound has a template dependent type.
template <class T>
void doSomething() {
  for (T i = 0; i < size(); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidForLoopInstantiation() {
  // This line does not trigger the warning.
  doSomething<long>();
  // This one triggers the warning.
  doSomething<short>();
}

// A suspicious function used in a macro.
#define SUSPICIOUS_SIZE (size())
void voidBadForLoopWithMacroBound() {
  for (short i = 0; i < SUSPICIOUS_SIZE; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Correct loops: we should not warn here.

// A simple use case when both expressions have the same type.
void voidGoodForLoop() {
  for (long i = 0; i < size(); ++i) { // no warning
  }
}

// Other use case where both expressions have the same type,
// but short expressions are converted to int by the compare operator.
void voidGoodForLoop2() {
  short loopCond = 10;
  for (short i = 0; i < loopCond; ++i) { // no warning
  }
}

// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
void voidForLoopShortPlusLiteral() {
  short size = 30000;
  for (short i = 0; i <= (size - 1); ++i) { // no warning
  }
}

// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
void voidForLoopShortPlusShort() {
  short size = 256;
  short increment = 14;
  for (short i = 0; i < size + increment; ++i) { // no warning
  }
}

// In this test case we have different integer types, but here the loop variable has the bigger type.
// The iteration's bound is cast implicitly, not the loop variable.
void voidForLoopBoundImplicitCast() {
  short start = 256;
  short end = 14;
  for (int i = start; i >= end; --i) { // no warning
  }
}

// Range based loop and other iterator based loops are ignored by this check.
void voidRangeBasedForLoop() {
  int array[] = {1, 2, 3, 4, 5};
  for (const int &i : array) { // no warning
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Future possibilites to improve the check.

// False positive: because of the int literal, iteration's upper bound has int type.
void voidForLoopFalsePositive() {
  short size = 30000;
  bool cond = false;
  for (short i = 0; i < (cond ? 0 : size); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
  }
}

void voidForLoopFalsePositive2() {
  short size = 30000;
  bool cond = false;
  for (short i = 0; i < (!cond ? size : 0); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
  }
}

// False positive: The loop bound expression contains nested binary operators.
void voidForLoopFalsePositive3() {
  short number = 30000;
  for (short i = 0; i < ((number & 0x7f) + 1); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
  }
}

// TODO: handle while loop.
void voidBadWhileLoop() {
  short i = 0;
  while (i < size()) { // missing warning
    ++i;
  }
}

// TODO: handle do-while loop.
void voidBadDoWhileLoop() {
  short i = 0;
  do {
    ++i;
  } while (i < size()); // missing warning
}

// TODO: handle complex loop conditions.
void voidComplexForCond() {
  bool additionalCond = true;
  for (int i = 0; i < size() && additionalCond; ++i) { // missing warning
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Suspicious test cases ingored by this check.

// Test case with a reverse iteration.
// This is caught by -Wimplicit-int-conversion.
void voidReverseForLoop() {
  for (short i = size() - 1; i >= 0; --i) { // no warning
  }
}

// Macro defined literals are used inside the loop condition.
#define SIZE 125
#define SIZE2 (SIZE + 1)
void voidForLoopWithMacroBound() {
  for (short i = 0; i < SIZE2; ++i) { // no warning
  }
}

// A suspicious loop is not caught if the iteration's upper bound is a literal.
void voidForLoopWithLiteralBound() {
  for (short i = 0; i < 125; ++i) { // no warning
  }
}

// The used literal leads to an infinite loop.
// This is caught by -Wtautological-constant-out-of-range-compare.
void voidForLoopWithBigLiteralBound() {
  for (short i = 0; i < 294967296l; ++i) { // no warning
  }
}

enum eSizeType {
  START,
  Y,
  END
};

// A suspicious loop is not caught if the iteration's upper bound is an enum value.
void voidForLoopWithEnumBound() {
  for (short i = eSizeType::START; i < eSizeType::END; ++i) { // no warning
  }
}

enum eSizeType2 : long {
  START2 = 294967296l,
  Y2,
  END2
};

// The used enum value leads to an infinite loop.
// This is caught by -Wtautological-constant-out-of-range-compare.
void voidForLoopWithBigEnumBound() {
  for (short i = eSizeType2::START2; i < eSizeType2::END2; ++i) { // no warning
  }
}

// A suspicious loop is not caught if the iteration's upper bound is a constant variable.
void voidForLoopWithConstBound() {
  const long size = 252l;
  for (short i = 0; i < size; ++i) { // no warning
  }
}

// The used constant variable leads to an infinite loop.
// This is caught by -Wtautological-constant-out-of-range-compare.
void voidForLoopWithBigConstBound() {
  const long size = 294967296l;
  for (short i = 0; i < size; ++i) { // no warning
  }
}
<commit_msg>[clang-tidy] fix ARM tests, because int and long have same width<commit_after>// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux

long size() { return 294967296l; }

////////////////////////////////////////////////////////////////////////////////
/// Test cases correctly caught by bugprone-too-small-loop-variable.

void voidBadForLoop() {
  for (int i = 0; i < size(); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop2() {
  for (int i = 0; i < size() + 10; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop3() {
  for (int i = 0; i <= size() - 1; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop4() {
  for (int i = 0; size() > i; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop5() {
  for (int i = 0; size() - 1 >= i; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidBadForLoop6() {
  int i = 0;
  for (; i < size(); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidForLoopUnsignedBound() {
  unsigned size = 3147483647;
  for (int i = 0; i < size; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
  }
}

// The iteration's upper bound has a template dependent value.
template <long size>
void doSomething() {
  for (short i = 0; i < size; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

// The iteration's upper bound has a template dependent type.
template <class T>
void doSomething() {
  for (T i = 0; i < size(); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

void voidForLoopInstantiation() {
  // This line does not trigger the warning.
  doSomething<long>();
  // This one triggers the warning.
  doSomething<short>();
}

// A suspicious function used in a macro.
#define SUSPICIOUS_SIZE (size())
void voidBadForLoopWithMacroBound() {
  for (short i = 0; i < SUSPICIOUS_SIZE; ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Correct loops: we should not warn here.

// A simple use case when both expressions have the same type.
void voidGoodForLoop() {
  for (long i = 0; i < size(); ++i) { // no warning
  }
}

// Other use case where both expressions have the same type,
// but short expressions are converted to int by the compare operator.
void voidGoodForLoop2() {
  short loopCond = 10;
  for (short i = 0; i < loopCond; ++i) { // no warning
  }
}

// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
void voidForLoopShortPlusLiteral() {
  short size = 30000;
  for (short i = 0; i <= (size - 1); ++i) { // no warning
  }
}

// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
void voidForLoopShortPlusShort() {
  short size = 256;
  short increment = 14;
  for (short i = 0; i < size + increment; ++i) { // no warning
  }
}

// In this test case we have different integer types, but here the loop variable has the bigger type.
// The iteration's bound is cast implicitly, not the loop variable.
void voidForLoopBoundImplicitCast() {
  short start = 256;
  short end = 14;
  for (int i = start; i >= end; --i) { // no warning
  }
}

// Range based loop and other iterator based loops are ignored by this check.
void voidRangeBasedForLoop() {
  int array[] = {1, 2, 3, 4, 5};
  for (const int &i : array) { // no warning
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Future possibilites to improve the check.

// False positive: because of the int literal, iteration's upper bound has int type.
void voidForLoopFalsePositive() {
  short size = 30000;
  bool cond = false;
  for (short i = 0; i < (cond ? 0 : size); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
  }
}

void voidForLoopFalsePositive2() {
  short size = 30000;
  bool cond = false;
  for (short i = 0; i < (!cond ? size : 0); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
  }
}

// False positive: The loop bound expression contains nested binary operators.
void voidForLoopFalsePositive3() {
  short number = 30000;
  for (short i = 0; i < ((number & 0x7f) + 1); ++i) {
    // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
  }
}

// TODO: handle while loop.
void voidBadWhileLoop() {
  short i = 0;
  while (i < size()) { // missing warning
    ++i;
  }
}

// TODO: handle do-while loop.
void voidBadDoWhileLoop() {
  short i = 0;
  do {
    ++i;
  } while (i < size()); // missing warning
}

// TODO: handle complex loop conditions.
void voidComplexForCond() {
  bool additionalCond = true;
  for (int i = 0; i < size() && additionalCond; ++i) { // missing warning
  }
}

////////////////////////////////////////////////////////////////////////////////
/// Suspicious test cases ingored by this check.

// Test case with a reverse iteration.
// This is caught by -Wimplicit-int-conversion.
void voidReverseForLoop() {
  for (short i = size() - 1; i >= 0; --i) { // no warning
  }
}

// Macro defined literals are used inside the loop condition.
#define SIZE 125
#define SIZE2 (SIZE + 1)
void voidForLoopWithMacroBound() {
  for (short i = 0; i < SIZE2; ++i) { // no warning
  }
}

// A suspicious loop is not caught if the iteration's upper bound is a literal.
void voidForLoopWithLiteralBound() {
  for (short i = 0; i < 125; ++i) { // no warning
  }
}

// The used literal leads to an infinite loop.
// This is caught by -Wtautological-constant-out-of-range-compare.
void voidForLoopWithBigLiteralBound() {
  for (short i = 0; i < 294967296l; ++i) { // no warning
  }
}

enum eSizeType {
  START,
  Y,
  END
};

// A suspicious loop is not caught if the iteration's upper bound is an enum value.
void voidForLoopWithEnumBound() {
  for (short i = eSizeType::START; i < eSizeType::END; ++i) { // no warning
  }
}

enum eSizeType2 : long {
  START2 = 294967296l,
  Y2,
  END2
};

// The used enum value leads to an infinite loop.
// This is caught by -Wtautological-constant-out-of-range-compare.
void voidForLoopWithBigEnumBound() {
  for (short i = eSizeType2::START2; i < eSizeType2::END2; ++i) { // no warning
  }
}

// A suspicious loop is not caught if the iteration's upper bound is a constant variable.
void voidForLoopWithConstBound() {
  const long size = 252l;
  for (short i = 0; i < size; ++i) { // no warning
  }
}

// The used constant variable leads to an infinite loop.
// This is caught by -Wtautological-constant-out-of-range-compare.
void voidForLoopWithBigConstBound() {
  const long size = 294967296l;
  for (short i = 0; i < size; ++i) { // no warning
  }
}
<|endoftext|>


<commit_before>/*
This file is part of HadesMem.
Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).
<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

HadesMem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HadesMem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HadesMem.  If not, see <http://www.gnu.org/licenses/>.
*/

// Hades
#include <HadesMemory/Injector.hpp>
#include <HadesMemory/Module.hpp>
#include <HadesMemory/MemoryMgr.hpp>
#include <HadesCommon/Filesystem.hpp>
#include <HadesCommon/EnsureCleanup.hpp>

// Windows API
#include <Windows.h>

// C++ Standard Library
#include <algorithm>

// Boost
#include <boost/algorithm/string.hpp>

// AsmJit
#ifdef HADES_MSVC
#pragma warning(push, 1)
#endif
#ifdef HADES_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-pedantic"
#pragma GCC diagnostic ignored "-Wattributes"
#pragma GCC diagnostic ignored "-Wparentheses"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include <AsmJit/AsmJit.h>
#ifdef HADES_MSVC
#pragma warning(pop)
#endif
#ifdef HADES_GCC
#pragma GCC diagnostic pop
#endif

namespace Hades
{
  namespace Memory
  {
    // This routine appends the given argument to a command line such
    // that CommandLineToArgvW will return the argument string unchanged.
    // Arguments in a command line should be separated by spaces; this
    // function does not add these spaces.
    void ArgvQuote(const std::wstring& Argument, std::wstring& CommandLine,
      bool Force)
    {
      // Unless we're told otherwise, don't quote unless we actually
      // need to do so --- hopefully avoid problems if programs won't
      // parse quotes properly
      if (!Force && !Argument.empty () && Argument.find_first_of(L" \t\n\v\"")
        == Argument.npos)
      {
        CommandLine.append(Argument);
      }
      else
      {
        CommandLine.push_back(L'"');

        for (auto It = Argument.begin(); ;++It)
        {
          unsigned NumberBackslashes = 0;

          while (It != Argument.end () && *It == L'\\')
          {
            ++It;
            ++NumberBackslashes;
          }

          if (It == Argument.end ())
          {
            // Escape all backslashes, but let the terminating
            // double quotation mark we add below be interpreted
            // as a metacharacter.
            CommandLine.append(NumberBackslashes * 2, L'\\');
            break;
          }
          else if (*It == L'"')
          {
            // Escape all backslashes and the following
            // double quotation mark.
            CommandLine.append(NumberBackslashes * 2 + 1, L'\\');
            CommandLine.push_back(*It);
          }
          else
          {
            // Backslashes aren't special here.
            CommandLine.append(NumberBackslashes, L'\\');
            CommandLine.push_back(*It);
          }
        }

        CommandLine.push_back(L'"');
      }
    }

    // Create process (as suspended) and inject DLL
    CreateAndInjectData CreateAndInject(
      boost::filesystem::path const& Path,
      boost::filesystem::path const& WorkDir,
      std::vector<std::wstring> const& Args,
      boost::filesystem::path const& Module,
      std::string const& Export,
      Injector::InjectFlags Flags)
    {
      // Set up args for CreateProcess
      STARTUPINFO StartInfo;
      ZeroMemory(&StartInfo, sizeof(StartInfo));
      StartInfo.cb = sizeof(StartInfo);
      PROCESS_INFORMATION ProcInfo;
      ZeroMemory(&ProcInfo, sizeof(ProcInfo));

      // Construct command line.
      std::wstring CommandLine;
      ArgvQuote(Path.native(), CommandLine, false);
      std::for_each(Args.begin(), Args.end(),
        [&] (std::wstring const& Arg)
        {
          CommandLine += L' ';
          ArgvQuote(Arg, CommandLine, false);
        });

      // Copy command line to buffer
      std::vector<wchar_t> ProcArgs(CommandLine.cbegin(), CommandLine.cend());
      ProcArgs.push_back(L'\0');

      // Set working directory
      boost::filesystem::path WorkDirReal;
      if (!WorkDir.empty())
      {
        WorkDirReal = WorkDir;
      }
      else if (Path.has_parent_path())
      {
        WorkDirReal = Path.parent_path();
      }
      else
      {
        WorkDirReal = L"./";
      }

      // Attempt process creation
      if (!CreateProcess(Path.c_str(), ProcArgs.data(), nullptr, nullptr, FALSE,
        CREATE_SUSPENDED, nullptr, WorkDirReal.c_str(), &StartInfo, &ProcInfo))
      {
        DWORD const LastError = GetLastError();
        BOOST_THROW_EXCEPTION(Injector::Error() <<
          ErrorFunction("CreateAndInject") <<
          ErrorString("Could not create process.") <<
          ErrorCodeWinLast(LastError));
      }

      // Ensure cleanup
      Windows::EnsureCloseHandle const ProcHandle(ProcInfo.hProcess);
      Windows::EnsureCloseHandle const ThreadHandle(ProcInfo.hThread);

      try
      {
        // Memory manager instance
        MemoryMgr const MyMemory(ProcInfo.dwProcessId);

        // Create Assembler.
        // This is used to generate a 'nullsub' function, which is called in
        // the context of the remote process in order to 'force' a call to
        // ntdll.dll!LdrInitializeThunk. This is necessary because module
        // enumeration will fail if LdrInitializeThunk has not been called,
        // and Injector::InjectDll (and the APIs it uses) depend on the
        // module enumeration APIs.
        AsmJit::Assembler MyJitFunc;

#if defined(_M_AMD64)
        // Return
        MyJitFunc.ret();
#elif defined(_M_IX86)
        // Return
        MyJitFunc.ret(AsmJit::Imm(0x4));
#else
#error "[HadesMem] Unsupported architecture."
#endif

        // Get stub size
        DWORD_PTR const StubSize = MyJitFunc.getCodeSize();

        // Allocate memory for stub buffer
        AllocAndFree const StubMemRemote(MyMemory, StubSize);
        PBYTE pRemoteStub = static_cast<PBYTE>(StubMemRemote.GetBase());
        DWORD_PTR pRemoteStubTemp = reinterpret_cast<DWORD_PTR>(pRemoteStub);

        // Create buffer to hold relocated code plus the return value address
        std::vector<BYTE> CodeReal(StubSize);

        // Generate code
        MyJitFunc.relocCode(CodeReal.data(), reinterpret_cast<DWORD_PTR>(
          pRemoteStub));

        // Write stub buffer to process
        MyMemory.Write(pRemoteStub, CodeReal);

        // Call stub via creating a remote thread in the target.
        Windows::EnsureCloseHandle const MyThread(CreateRemoteThread(
          MyMemory.GetProcessHandle(), nullptr, 0,
          reinterpret_cast<LPTHREAD_START_ROUTINE>(pRemoteStubTemp), nullptr,
          0, nullptr));
        if (!MyThread)
        {
          DWORD const LastError = GetLastError();
          BOOST_THROW_EXCEPTION(Injector::Error() <<
            ErrorFunction("CreateAndInject") <<
            ErrorString("Could not create remote thread.") <<
            ErrorCodeWinLast(LastError));
        }

        // Wait for the remote thread to terminate
        if (WaitForSingleObject(MyThread, INFINITE) != WAIT_OBJECT_0)
        {
          DWORD const LastError = GetLastError();
          BOOST_THROW_EXCEPTION(Injector::Error() <<
            ErrorFunction("CreateAndInject") <<
            ErrorString("Could not wait for remote thread.") <<
            ErrorCodeWinLast(LastError));
        }

        // Create DLL injector
        Injector const MyInjector(MyMemory);

        // Inject DLL
        HMODULE const ModBase = MyInjector.InjectDll(Module, Flags);

        // Call export if one has been specified
        MemoryMgr::RemoteFunctionRet ExpRetData;
        if (!Export.empty())
        {
          ExpRetData = MyInjector.CallExport(Module, ModBase, Export);
        }

        // Success! Let the process continue execution.
        if (ResumeThread(ProcInfo.hThread) == static_cast<DWORD>(-1))
        {
          DWORD const LastError = GetLastError();
          BOOST_THROW_EXCEPTION(Injector::Error() <<
            ErrorFunction("CreateAndInject") <<
            ErrorString("Could not resume process.") <<
            ErrorCodeWinLast(LastError) <<
            ErrorCodeWinRet(ExpRetData.GetReturnValue()) <<
            ErrorCodeWinOther(ExpRetData.GetLastError()));
        }

        // Return data to caller
        return CreateAndInjectData(MyMemory, ModBase,
          ExpRetData.GetReturnValue(), ExpRetData.GetLastError());
      }
      // Catch exceptions
      catch (std::exception const& /*e*/)
      {
        // Terminate process if injection failed
        TerminateProcess(ProcInfo.hProcess, 0);

        // Rethrow exception
        throw;
      }
    }

    // Constructor
    Injector::Injector(MemoryMgr const& MyMemory)
      : m_Memory(MyMemory)
    { }

    // Inject DLL
    HMODULE Injector::InjectDll(boost::filesystem::path const& Path,
      InjectFlags Flags) const
    {
      // Do not continue if Shim Engine is enabled for local process,
      // otherwise it could interfere with the address resolution.
      HMODULE const ShimEngMod = GetModuleHandle(L"ShimEng.dll");
      if (ShimEngMod)
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::InjectDll") <<
          ErrorString("Shims enabled for local process."));
      }

      // String to hold 'real' path to module
      boost::filesystem::path PathReal(Path);

      // Check if path resolution was requested
      bool PathResolution = ((Flags & InjectFlag_PathResolution) ==
        InjectFlag_PathResolution);

      // Check whether we need to convert the path from a relative to
      // an absolute
      if (PathResolution && PathReal.is_relative())
      {
        // Convert relative path to absolute path
        PathReal = boost::filesystem::absolute(PathReal, Hades::Windows::
          GetSelfDirPath());
      }

      // Convert path to preferred format
      PathReal.make_preferred();

      // Ensure target file exists
      // Note: Only performing this check when path resolution is enabled,
      // because otherwise we would need to perform the check in the context
      // of the remote process, which is not possible to do without
      // introducing race conditions and other potential problems. So we just
      // let LoadLibraryW do the check for us.
      if (PathResolution && !boost::filesystem::exists(PathReal))
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::InjectDll") <<
          ErrorString("Could not find module file."));
      }

      // Get path as string
      std::wstring const PathString(PathReal.native());

      // Calculate the number of bytes needed for the DLL's pathname
      std::size_t const PathBufSize = (PathString.size() + 1) *
        sizeof(wchar_t);

      // Allocate space in the remote process for the pathname
      AllocAndFree const LibFileRemote(m_Memory, PathBufSize);

      // Copy the DLL's pathname to the remote process' address space
      m_Memory.Write(LibFileRemote.GetBase(), PathString);

      // Get address of LoadLibraryW in Kernel32.dll
      Module Kernel32Mod(m_Memory, L"kernel32.dll");
      FARPROC const pLoadLibraryW = m_Memory.GetRemoteProcAddress(
        Kernel32Mod.GetBase(), "kernel32.dll", "LoadLibraryW");
      DWORD_PTR pLoadLibraryWTemp = reinterpret_cast<DWORD_PTR>(pLoadLibraryW);

      // Load module in remote process using LoadLibraryW
      std::vector<PVOID> Args;
      Args.push_back(LibFileRemote.GetBase());
      MemoryMgr::RemoteFunctionRet RemoteRet = m_Memory.Call(
        reinterpret_cast<PVOID>(pLoadLibraryWTemp),
        MemoryMgr::CallConv_Default, Args);
      if (!RemoteRet.GetReturnValue())
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::InjectDll") <<
          ErrorString("Call to LoadLibraryW in remote process failed.") <<
          ErrorCodeWinLast(RemoteRet.GetLastError()));
      }

      // Look for target module
      Module NewModule(m_Memory, reinterpret_cast<HMODULE>(
        RemoteRet.GetReturnValue()));

      // Return module base
      return NewModule.GetBase();
    }

    // Free DLL
    void Injector::FreeDll(HMODULE ModuleRemote) const
    {
      // Get address of FreeLibrary in Kernel32.dll
      Module Kernel32Mod(m_Memory, L"kernel32.dll");
      FARPROC const pFreeLibrary = m_Memory.GetRemoteProcAddress(
        Kernel32Mod.GetBase(), "kernel32.dll", "FreeLibrary");
      DWORD_PTR pFreeLibraryTemp = reinterpret_cast<DWORD_PTR>(pFreeLibrary);

      // Free module in remote process using FreeLibrary
      std::vector<PVOID> Args;
      Args.push_back(reinterpret_cast<PVOID>(ModuleRemote));
      MemoryMgr::RemoteFunctionRet RemoteRet = m_Memory.Call(
        reinterpret_cast<PVOID>(pFreeLibraryTemp),
        MemoryMgr::CallConv_Default, Args);
      if (!RemoteRet.GetReturnValue())
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::FreeDll") <<
          ErrorString("Call to FreeLibrary in remote process failed.") <<
          ErrorCodeWinLast(RemoteRet.GetLastError()));
      }
    }

    // Call export
    MemoryMgr::RemoteFunctionRet Injector::CallExport(
      boost::filesystem::path const& ModulePath,
      HMODULE ModuleRemote, std::string const& Export) const
    {
      // Get export address
      FARPROC const pExportAddr = m_Memory.GetRemoteProcAddress(ModuleRemote,
        ModulePath, Export);
      DWORD_PTR const pExportAddrTemp = reinterpret_cast<DWORD_PTR>(
        pExportAddr);

      // Create a remote thread that calls the desired export
      std::vector<PVOID> ExportArgs;
      ExportArgs.push_back(ModuleRemote);
      return m_Memory.Call(reinterpret_cast<PVOID>(pExportAddrTemp),
        MemoryMgr::CallConv_Default, ExportArgs);
    }
  }
}
<commit_msg>* [Injector] Simplify InjectDll a little bit. (No longer need to do module enum because MemoryMgr::Call returns a 64-bit value on x64)<commit_after>/*
This file is part of HadesMem.
Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).
<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

HadesMem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HadesMem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HadesMem.  If not, see <http://www.gnu.org/licenses/>.
*/

// Hades
#include <HadesMemory/Injector.hpp>
#include <HadesMemory/Module.hpp>
#include <HadesMemory/MemoryMgr.hpp>
#include <HadesCommon/Filesystem.hpp>
#include <HadesCommon/EnsureCleanup.hpp>

// Windows API
#include <Windows.h>

// C++ Standard Library
#include <algorithm>

// Boost
#include <boost/algorithm/string.hpp>

// AsmJit
#ifdef HADES_MSVC
#pragma warning(push, 1)
#endif
#ifdef HADES_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-pedantic"
#pragma GCC diagnostic ignored "-Wattributes"
#pragma GCC diagnostic ignored "-Wparentheses"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include <AsmJit/AsmJit.h>
#ifdef HADES_MSVC
#pragma warning(pop)
#endif
#ifdef HADES_GCC
#pragma GCC diagnostic pop
#endif

namespace Hades
{
  namespace Memory
  {
    // This routine appends the given argument to a command line such
    // that CommandLineToArgvW will return the argument string unchanged.
    // Arguments in a command line should be separated by spaces; this
    // function does not add these spaces.
    void ArgvQuote(const std::wstring& Argument, std::wstring& CommandLine,
      bool Force)
    {
      // Unless we're told otherwise, don't quote unless we actually
      // need to do so --- hopefully avoid problems if programs won't
      // parse quotes properly
      if (!Force && !Argument.empty () && Argument.find_first_of(L" \t\n\v\"")
        == Argument.npos)
      {
        CommandLine.append(Argument);
      }
      else
      {
        CommandLine.push_back(L'"');

        for (auto It = Argument.begin(); ;++It)
        {
          unsigned NumberBackslashes = 0;

          while (It != Argument.end () && *It == L'\\')
          {
            ++It;
            ++NumberBackslashes;
          }

          if (It == Argument.end ())
          {
            // Escape all backslashes, but let the terminating
            // double quotation mark we add below be interpreted
            // as a metacharacter.
            CommandLine.append(NumberBackslashes * 2, L'\\');
            break;
          }
          else if (*It == L'"')
          {
            // Escape all backslashes and the following
            // double quotation mark.
            CommandLine.append(NumberBackslashes * 2 + 1, L'\\');
            CommandLine.push_back(*It);
          }
          else
          {
            // Backslashes aren't special here.
            CommandLine.append(NumberBackslashes, L'\\');
            CommandLine.push_back(*It);
          }
        }

        CommandLine.push_back(L'"');
      }
    }

    // Create process (as suspended) and inject DLL
    CreateAndInjectData CreateAndInject(
      boost::filesystem::path const& Path,
      boost::filesystem::path const& WorkDir,
      std::vector<std::wstring> const& Args,
      boost::filesystem::path const& Module,
      std::string const& Export,
      Injector::InjectFlags Flags)
    {
      // Set up args for CreateProcess
      STARTUPINFO StartInfo;
      ZeroMemory(&StartInfo, sizeof(StartInfo));
      StartInfo.cb = sizeof(StartInfo);
      PROCESS_INFORMATION ProcInfo;
      ZeroMemory(&ProcInfo, sizeof(ProcInfo));

      // Construct command line.
      std::wstring CommandLine;
      ArgvQuote(Path.native(), CommandLine, false);
      std::for_each(Args.begin(), Args.end(),
        [&] (std::wstring const& Arg)
        {
          CommandLine += L' ';
          ArgvQuote(Arg, CommandLine, false);
        });

      // Copy command line to buffer
      std::vector<wchar_t> ProcArgs(CommandLine.cbegin(), CommandLine.cend());
      ProcArgs.push_back(L'\0');

      // Set working directory
      boost::filesystem::path WorkDirReal;
      if (!WorkDir.empty())
      {
        WorkDirReal = WorkDir;
      }
      else if (Path.has_parent_path())
      {
        WorkDirReal = Path.parent_path();
      }
      else
      {
        WorkDirReal = L"./";
      }

      // Attempt process creation
      if (!CreateProcess(Path.c_str(), ProcArgs.data(), nullptr, nullptr, FALSE,
        CREATE_SUSPENDED, nullptr, WorkDirReal.c_str(), &StartInfo, &ProcInfo))
      {
        DWORD const LastError = GetLastError();
        BOOST_THROW_EXCEPTION(Injector::Error() <<
          ErrorFunction("CreateAndInject") <<
          ErrorString("Could not create process.") <<
          ErrorCodeWinLast(LastError));
      }

      // Ensure cleanup
      Windows::EnsureCloseHandle const ProcHandle(ProcInfo.hProcess);
      Windows::EnsureCloseHandle const ThreadHandle(ProcInfo.hThread);

      try
      {
        // Memory manager instance
        MemoryMgr const MyMemory(ProcInfo.dwProcessId);

        // Create Assembler.
        // This is used to generate a 'nullsub' function, which is called in
        // the context of the remote process in order to 'force' a call to
        // ntdll.dll!LdrInitializeThunk. This is necessary because module
        // enumeration will fail if LdrInitializeThunk has not been called,
        // and Injector::InjectDll (and the APIs it uses) depend on the
        // module enumeration APIs.
        AsmJit::Assembler MyJitFunc;

#if defined(_M_AMD64)
        // Return
        MyJitFunc.ret();
#elif defined(_M_IX86)
        // Return
        MyJitFunc.ret(AsmJit::Imm(0x4));
#else
#error "[HadesMem] Unsupported architecture."
#endif

        // Get stub size
        DWORD_PTR const StubSize = MyJitFunc.getCodeSize();

        // Allocate memory for stub buffer
        AllocAndFree const StubMemRemote(MyMemory, StubSize);
        PBYTE pRemoteStub = static_cast<PBYTE>(StubMemRemote.GetBase());
        DWORD_PTR pRemoteStubTemp = reinterpret_cast<DWORD_PTR>(pRemoteStub);

        // Create buffer to hold relocated code plus the return value address
        std::vector<BYTE> CodeReal(StubSize);

        // Generate code
        MyJitFunc.relocCode(CodeReal.data(), reinterpret_cast<DWORD_PTR>(
          pRemoteStub));

        // Write stub buffer to process
        MyMemory.Write(pRemoteStub, CodeReal);

        // Call stub via creating a remote thread in the target.
        Windows::EnsureCloseHandle const MyThread(CreateRemoteThread(
          MyMemory.GetProcessHandle(), nullptr, 0,
          reinterpret_cast<LPTHREAD_START_ROUTINE>(pRemoteStubTemp), nullptr,
          0, nullptr));
        if (!MyThread)
        {
          DWORD const LastError = GetLastError();
          BOOST_THROW_EXCEPTION(Injector::Error() <<
            ErrorFunction("CreateAndInject") <<
            ErrorString("Could not create remote thread.") <<
            ErrorCodeWinLast(LastError));
        }

        // Wait for the remote thread to terminate
        if (WaitForSingleObject(MyThread, INFINITE) != WAIT_OBJECT_0)
        {
          DWORD const LastError = GetLastError();
          BOOST_THROW_EXCEPTION(Injector::Error() <<
            ErrorFunction("CreateAndInject") <<
            ErrorString("Could not wait for remote thread.") <<
            ErrorCodeWinLast(LastError));
        }

        // Create DLL injector
        Injector const MyInjector(MyMemory);

        // Inject DLL
        HMODULE const ModBase = MyInjector.InjectDll(Module, Flags);

        // Call export if one has been specified
        MemoryMgr::RemoteFunctionRet ExpRetData;
        if (!Export.empty())
        {
          ExpRetData = MyInjector.CallExport(Module, ModBase, Export);
        }

        // Success! Let the process continue execution.
        if (ResumeThread(ProcInfo.hThread) == static_cast<DWORD>(-1))
        {
          DWORD const LastError = GetLastError();
          BOOST_THROW_EXCEPTION(Injector::Error() <<
            ErrorFunction("CreateAndInject") <<
            ErrorString("Could not resume process.") <<
            ErrorCodeWinLast(LastError) <<
            ErrorCodeWinRet(ExpRetData.GetReturnValue()) <<
            ErrorCodeWinOther(ExpRetData.GetLastError()));
        }

        // Return data to caller
        return CreateAndInjectData(MyMemory, ModBase,
          ExpRetData.GetReturnValue(), ExpRetData.GetLastError());
      }
      // Catch exceptions
      catch (std::exception const& /*e*/)
      {
        // Terminate process if injection failed
        TerminateProcess(ProcInfo.hProcess, 0);

        // Rethrow exception
        throw;
      }
    }

    // Constructor
    Injector::Injector(MemoryMgr const& MyMemory)
      : m_Memory(MyMemory)
    { }

    // Inject DLL
    HMODULE Injector::InjectDll(boost::filesystem::path const& Path,
      InjectFlags Flags) const
    {
      // Do not continue if Shim Engine is enabled for local process,
      // otherwise it could interfere with the address resolution.
      HMODULE const ShimEngMod = GetModuleHandle(L"ShimEng.dll");
      if (ShimEngMod)
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::InjectDll") <<
          ErrorString("Shims enabled for local process."));
      }

      // String to hold 'real' path to module
      boost::filesystem::path PathReal(Path);

      // Check if path resolution was requested
      bool PathResolution = ((Flags & InjectFlag_PathResolution) ==
        InjectFlag_PathResolution);

      // Check whether we need to convert the path from a relative to
      // an absolute
      if (PathResolution && PathReal.is_relative())
      {
        // Convert relative path to absolute path
        PathReal = boost::filesystem::absolute(PathReal, Hades::Windows::
          GetSelfDirPath());
      }

      // Convert path to preferred format
      PathReal.make_preferred();

      // Ensure target file exists
      // Note: Only performing this check when path resolution is enabled,
      // because otherwise we would need to perform the check in the context
      // of the remote process, which is not possible to do without
      // introducing race conditions and other potential problems. So we just
      // let LoadLibraryW do the check for us.
      if (PathResolution && !boost::filesystem::exists(PathReal))
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::InjectDll") <<
          ErrorString("Could not find module file."));
      }

      // Get path as string
      std::wstring const PathString(PathReal.native());

      // Calculate the number of bytes needed for the DLL's pathname
      std::size_t const PathBufSize = (PathString.size() + 1) *
        sizeof(wchar_t);

      // Allocate space in the remote process for the pathname
      AllocAndFree const LibFileRemote(m_Memory, PathBufSize);

      // Copy the DLL's pathname to the remote process' address space
      m_Memory.Write(LibFileRemote.GetBase(), PathString);

      // Get address of LoadLibraryW in Kernel32.dll
      Module Kernel32Mod(m_Memory, L"kernel32.dll");
      FARPROC const pLoadLibraryW = m_Memory.GetRemoteProcAddress(
        Kernel32Mod.GetBase(), "kernel32.dll", "LoadLibraryW");
      DWORD_PTR pLoadLibraryWTemp = reinterpret_cast<DWORD_PTR>(pLoadLibraryW);

      // Load module in remote process using LoadLibraryW
      std::vector<PVOID> Args;
      Args.push_back(LibFileRemote.GetBase());
      MemoryMgr::RemoteFunctionRet RemoteRet = m_Memory.Call(
        reinterpret_cast<PVOID>(pLoadLibraryWTemp),
        MemoryMgr::CallConv_Default, Args);
      if (!RemoteRet.GetReturnValue())
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::InjectDll") <<
          ErrorString("Call to LoadLibraryW in remote process failed.") <<
          ErrorCodeWinLast(RemoteRet.GetLastError()));
      }

      // Return module base
      return reinterpret_cast<HMODULE>(RemoteRet.GetReturnValue());
    }

    // Free DLL
    void Injector::FreeDll(HMODULE ModuleRemote) const
    {
      // Get address of FreeLibrary in Kernel32.dll
      Module Kernel32Mod(m_Memory, L"kernel32.dll");
      FARPROC const pFreeLibrary = m_Memory.GetRemoteProcAddress(
        Kernel32Mod.GetBase(), "kernel32.dll", "FreeLibrary");
      DWORD_PTR pFreeLibraryTemp = reinterpret_cast<DWORD_PTR>(pFreeLibrary);

      // Free module in remote process using FreeLibrary
      std::vector<PVOID> Args;
      Args.push_back(reinterpret_cast<PVOID>(ModuleRemote));
      MemoryMgr::RemoteFunctionRet RemoteRet = m_Memory.Call(
        reinterpret_cast<PVOID>(pFreeLibraryTemp),
        MemoryMgr::CallConv_Default, Args);
      if (!RemoteRet.GetReturnValue())
      {
        BOOST_THROW_EXCEPTION(Error() <<
          ErrorFunction("Injector::FreeDll") <<
          ErrorString("Call to FreeLibrary in remote process failed.") <<
          ErrorCodeWinLast(RemoteRet.GetLastError()));
      }
    }

    // Call export
    MemoryMgr::RemoteFunctionRet Injector::CallExport(
      boost::filesystem::path const& ModulePath,
      HMODULE ModuleRemote, std::string const& Export) const
    {
      // Get export address
      FARPROC const pExportAddr = m_Memory.GetRemoteProcAddress(ModuleRemote,
        ModulePath, Export);
      DWORD_PTR const pExportAddrTemp = reinterpret_cast<DWORD_PTR>(
        pExportAddr);

      // Create a remote thread that calls the desired export
      std::vector<PVOID> ExportArgs;
      ExportArgs.push_back(ModuleRemote);
      return m_Memory.Call(reinterpret_cast<PVOID>(pExportAddrTemp),
        MemoryMgr::CallConv_Default, ExportArgs);
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <random.h>

#include <crypto/sha512.h>
#include <support/cleanse.h>
#ifdef WIN32
#include <compat.h> // for Windows API
#include <wincrypt.h>
#endif
#include <util.h>             // for LogPrint()
#include <utilstrencodings.h> // for GetTime()

#include <stdlib.h>
#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <sys/syscall.h>
#include <linux/random.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LogPrintf("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(vData.data(), nSize, nSize / 100.0);
        memory_cleanse(vData.data(), nSize);
        LogPrint(BCLog::RAND, "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
 * compatible way to get cryptographic randomness on UNIX-ish platforms.
 */
void GetDevURandom(unsigned char *ent32)
{
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1) {
        RandFailure();
    }
    int have = 0;
    do {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
}
#endif

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#if defined(WIN32)
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret) {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret) {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
    if (rv != NUM_OS_RANDOM_BYTES) {
        if (rv < 0 && errno == ENOSYS) {
            /* Fallback for kernel <3.17: the return value will be -1 and errno
             * ENOSYS if the syscall is not available, in that case fall back
             * to /dev/urandom.
             */
            GetDevURandom(ent32);
        } else {
            RandFailure();
        }
    }
#elif defined(HAVE_GETENTROPY)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    GetDevURandom(ent32);
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        RandFailure();
    }
}

void GetStrongRandBytes(unsigned char* out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Produce output
    hasher.Finalize(buf);
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

void FastRandomContext::RandomSeed()
{
    uint256 seed = GetRandHash();
    rng.SetKey(seed.begin(), 32);
    requires_seed = false;
}

FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{
    rng.SetKey(seed.begin(), 32);
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            if (overwritten[x]) {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}

FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
{
    if (!fDeterministic) {
        return;
    }
    uint256 seed;
    rng.SetKey(seed.begin(), 32);
}
<commit_msg>Maintain state across GetStrongRandBytes calls<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <random.h>

#include <crypto/sha512.h>
#include <support/cleanse.h>
#ifdef WIN32
#include <compat.h> // for Windows API
#include <wincrypt.h>
#endif
#include <util.h>             // for LogPrint()
#include <utilstrencodings.h> // for GetTime()

#include <stdlib.h>
#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <sys/syscall.h>
#include <linux/random.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <mutex>

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LogPrintf("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(vData.data(), nSize, nSize / 100.0);
        memory_cleanse(vData.data(), nSize);
        LogPrint(BCLog::RAND, "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
 * compatible way to get cryptographic randomness on UNIX-ish platforms.
 */
void GetDevURandom(unsigned char *ent32)
{
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1) {
        RandFailure();
    }
    int have = 0;
    do {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
}
#endif

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#if defined(WIN32)
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret) {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret) {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
    if (rv != NUM_OS_RANDOM_BYTES) {
        if (rv < 0 && errno == ENOSYS) {
            /* Fallback for kernel <3.17: the return value will be -1 and errno
             * ENOSYS if the syscall is not available, in that case fall back
             * to /dev/urandom.
             */
            GetDevURandom(ent32);
        } else {
            RandFailure();
        }
    }
#elif defined(HAVE_GETENTROPY)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    GetDevURandom(ent32);
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        RandFailure();
    }
}

static std::mutex cs_rng_state;
static unsigned char rng_state[32] = {0};
static uint64_t rng_counter = 0;

void GetStrongRandBytes(unsigned char* out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Combine with and update state
    {
        std::unique_lock<std::mutex> lock(cs_rng_state);
        hasher.Write(rng_state, sizeof(rng_state));
        hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
        ++rng_counter;
        hasher.Finalize(buf);
        memcpy(rng_state, buf + 32, 32);
    }

    // Produce output
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

void FastRandomContext::RandomSeed()
{
    uint256 seed = GetRandHash();
    rng.SetKey(seed.begin(), 32);
    requires_seed = false;
}

FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{
    rng.SetKey(seed.begin(), 32);
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            if (overwritten[x]) {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}

FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
{
    if (!fDeterministic) {
        return;
    }
    uint256 seed;
    rng.SetKey(seed.begin(), 32);
}
<|endoftext|>


<commit_before>#include <condition_variable>
#include <functional>
#include <list>
#include <mutex>
#include <string>
#include <thread>
#include <queue>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "thread-capture.h"
#include "thread-crosser.h"

using testing::ElementsAre;

namespace {

class LogText : public ThreadCapture<LogText> {
 public:
  LogText() : cross_and_capture_to_(this) {}

  static void Log(std::string line) {
    if (GetCurrent()) {
      GetCurrent()->LogLine(std::move(line));
    }
  }

  const std::list<std::string> GetLinesUnsafe() {
    return lines_;
  }

 private:
  void LogLine(std::string line) {
    std::lock_guard<std::mutex> lock(data_lock_);
    lines_.emplace_back(std::move(line));
  }

  std::mutex data_lock_;
  std::list<std::string> lines_;
  const AutoThreadCrosser<LogText> cross_and_capture_to_;
};

class LogValues : public ThreadCapture<LogValues> {
 public:
  LogValues() : cross_and_capture_to_(this) {}

  static void Count(int count) {
    if (GetCurrent()) {
      GetCurrent()->LogCount(count);
    }
  }

  const std::list<int> GetCountsUnsafe() {
    return counts_;
  }

 private:
  void LogCount(int count) {
    std::lock_guard<std::mutex> lock(data_lock_);
    counts_.emplace_back(count);
  }

  std::mutex data_lock_;
  std::list<int> counts_;
  const AutoThreadCrosser<LogValues> cross_and_capture_to_;
};

class BlockingCallbackQueue {
 public:
  void Push(std::function<void()> callback) {
    std::lock_guard<std::mutex> lock(queue_lock_);
    queue_.push(std::move(callback));
    condition_.notify_all();
  }

  // NOTE: Calling before returning avoids a race condition if WaitUntilEmpty()
  // is used to wait until all calls complete.
  bool PopAndCall() {
    std::unique_lock<std::mutex> lock(queue_lock_);
    while (queue_.empty()) {
      condition_.wait(lock);
    }
    const bool valid = queue_.front().operator bool();
    if (valid) {
      queue_.front()();
      queue_.pop();
      condition_.notify_all();
    }
    return valid;
  }

  void WaitUntilEmpty() {
    std::unique_lock<std::mutex> lock(queue_lock_);
    while (!queue_.empty()) {
      condition_.wait(lock);
    }
  }

 private:
  std::mutex queue_lock_;
  std::condition_variable condition_;
  std::queue<std::function<void()>> queue_;
};

}  // namespace

TEST(ThreadCaptureTest, NoLoggerInterferenceWithDifferentTypes) {
  LogText::Log("not logged");
  LogValues::Count(0);
  {
    LogText text_logger;
    LogText::Log("logged 1");
    {
      LogValues count_logger;
      LogValues::Count(1);
      LogText::Log("logged 2");
      EXPECT_THAT(count_logger.GetCountsUnsafe(), ElementsAre(1));
    }
    LogText::Log("logged 3");
    EXPECT_THAT(text_logger.GetLinesUnsafe(),
                ElementsAre("logged 1", "logged 2", "logged 3"));
  }
}

TEST(ThreadCaptureTest, SameTypeOverrides) {
    LogText text_logger1;
    LogText::Log("logged 1");
    {
      LogText text_logger2;
      LogText::Log("logged 2");
      EXPECT_THAT(text_logger2.GetLinesUnsafe(), ElementsAre("logged 2"));
    }
    LogText::Log("logged 3");
    EXPECT_THAT(text_logger1.GetLinesUnsafe(),
                ElementsAre("logged 1", "logged 3"));
}

TEST(ThreadCaptureTest, ThreadsAreNotCrossed) {
  LogText logger;
  LogText::Log("logged 1");

  std::thread worker([] {
        LogText::Log("logged 2");
      });
  worker.join();

  EXPECT_THAT(logger.GetLinesUnsafe(), ElementsAre("logged 1"));
}

TEST(ThreadCrosserTest, WrapCallIsFineWithoutLogger) {
  bool called = false;
  ThreadCrosser::WrapCall([&called] {
      called = true;
      LogText::Log("not logged");
    })();
  EXPECT_TRUE(called);
}

TEST(ThreadCrosserTest, WrapCallWithNullCallbackIsNull) {
  EXPECT_FALSE(ThreadCrosser::WrapCall(nullptr));
  LogText logger;
  EXPECT_FALSE(ThreadCrosser::WrapCall(nullptr));
}

TEST(ThreadCrosserTest, SingleThreadCrossing) {
  LogText logger;
  LogText::Log("logged 1");

  std::thread worker(ThreadCrosser::WrapCall([] {
        LogText::Log("logged 2");
      }));
  worker.join();

  EXPECT_THAT(logger.GetLinesUnsafe(), ElementsAre("logged 1", "logged 2"));
}

TEST(ThreadCrosserTest, MultipleThreadCrossingWithMultipleLoggers) {
  LogText text_logger;
  LogText::Log("logged 1");
  LogValues count_logger;
  LogValues::Count(1);

  std::thread worker(ThreadCrosser::WrapCall([] {
        std::thread worker(ThreadCrosser::WrapCall([] {
              LogText::Log("logged 2");
              LogValues::Count(2);
            }));
        worker.join();
      }));
  worker.join();

  EXPECT_THAT(text_logger.GetLinesUnsafe(),
              ElementsAre("logged 1", "logged 2"));
  EXPECT_THAT(count_logger.GetCountsUnsafe(), ElementsAre(1, 2));
}

TEST(ThreadCrosserTest, MultipleThreadCrossingWithDifferentLoggerScopes) {
  LogText text_logger;

  std::thread worker(ThreadCrosser::WrapCall([] {
        LogValues count_logger;
        std::thread worker(ThreadCrosser::WrapCall([] {
              LogText::Log("logged 1");
              LogValues::Count(1);
            }));
        worker.join();
        EXPECT_THAT(count_logger.GetCountsUnsafe(), ElementsAre(1));
      }));
  worker.join();

  EXPECT_THAT(text_logger.GetLinesUnsafe(), ElementsAre("logged 1"));
}

TEST(ThreadCrosserTest, DifferentLoggersInSameThread) {
  BlockingCallbackQueue queue;

  std::thread worker([&queue] {
        while (true) {
          LogText logger;
          if (!queue.PopAndCall()) {
            break;
          }
          LogText::Log("logged in thread");
          EXPECT_THAT(logger.GetLinesUnsafe(), ElementsAre("logged in thread"));
        }
      });

  LogText logger1;
  queue.Push(ThreadCrosser::WrapCall([] {
        LogText::Log("logged 1");
      }));
  queue.WaitUntilEmpty();
  EXPECT_THAT(logger1.GetLinesUnsafe(), ElementsAre("logged 1"));

  {
    // It's important for the test case that logger2 overrides logger1, i.e.,
    // that they are both in scope at the same time.
    LogText logger2;
    queue.Push(ThreadCrosser::WrapCall([] {
          LogText::Log("logged 2");
        }));
    queue.WaitUntilEmpty();
    EXPECT_THAT(logger2.GetLinesUnsafe(), ElementsAre("logged 2"));
  }

  queue.Push(ThreadCrosser::WrapCall([] {
        LogText::Log("logged 3");
      }));
  queue.WaitUntilEmpty();
  EXPECT_THAT(logger1.GetLinesUnsafe(), ElementsAre("logged 1", "logged 3"));

  queue.Push(nullptr);  // (Causes the thread to exit.)
  worker.join();
}

int main(int argc, char *argv[]) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Fixes latent bug in unit test.<commit_after>#include <condition_variable>
#include <functional>
#include <list>
#include <mutex>
#include <string>
#include <thread>
#include <queue>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "thread-capture.h"
#include "thread-crosser.h"

using testing::ElementsAre;

namespace {

class LogText : public ThreadCapture<LogText> {
 public:
  LogText() : cross_and_capture_to_(this) {}

  static void Log(std::string line) {
    if (GetCurrent()) {
      GetCurrent()->LogLine(std::move(line));
    }
  }

  const std::list<std::string> GetLinesUnsafe() {
    return lines_;
  }

 private:
  void LogLine(std::string line) {
    std::lock_guard<std::mutex> lock(data_lock_);
    lines_.emplace_back(std::move(line));
  }

  std::mutex data_lock_;
  std::list<std::string> lines_;
  const AutoThreadCrosser<LogText> cross_and_capture_to_;
};

class LogValues : public ThreadCapture<LogValues> {
 public:
  LogValues() : cross_and_capture_to_(this) {}

  static void Count(int count) {
    if (GetCurrent()) {
      GetCurrent()->LogCount(count);
    }
  }

  const std::list<int> GetCountsUnsafe() {
    return counts_;
  }

 private:
  void LogCount(int count) {
    std::lock_guard<std::mutex> lock(data_lock_);
    counts_.emplace_back(count);
  }

  std::mutex data_lock_;
  std::list<int> counts_;
  const AutoThreadCrosser<LogValues> cross_and_capture_to_;
};

class BlockingCallbackQueue {
 public:
  void Push(std::function<void()> callback) {
    std::lock_guard<std::mutex> lock(queue_lock_);
    queue_.push(std::move(callback));
    condition_.notify_all();
  }

  // NOTE: Calling before returning avoids a race condition if WaitUntilEmpty()
  // is used to wait until all calls complete.
  bool PopAndCall() {
    std::unique_lock<std::mutex> lock(queue_lock_);
    while (queue_.empty()) {
      condition_.wait(lock);
    }
    const bool valid = queue_.front().operator bool();
    if (valid) {
      queue_.front()();
    }
    queue_.pop();
    condition_.notify_all();
    return valid;
  }

  void WaitUntilEmpty() {
    std::unique_lock<std::mutex> lock(queue_lock_);
    while (!queue_.empty()) {
      condition_.wait(lock);
    }
  }

 private:
  std::mutex queue_lock_;
  std::condition_variable condition_;
  std::queue<std::function<void()>> queue_;
};

}  // namespace

TEST(ThreadCaptureTest, NoLoggerInterferenceWithDifferentTypes) {
  LogText::Log("not logged");
  LogValues::Count(0);
  {
    LogText text_logger;
    LogText::Log("logged 1");
    {
      LogValues count_logger;
      LogValues::Count(1);
      LogText::Log("logged 2");
      EXPECT_THAT(count_logger.GetCountsUnsafe(), ElementsAre(1));
    }
    LogText::Log("logged 3");
    EXPECT_THAT(text_logger.GetLinesUnsafe(),
                ElementsAre("logged 1", "logged 2", "logged 3"));
  }
}

TEST(ThreadCaptureTest, SameTypeOverrides) {
    LogText text_logger1;
    LogText::Log("logged 1");
    {
      LogText text_logger2;
      LogText::Log("logged 2");
      EXPECT_THAT(text_logger2.GetLinesUnsafe(), ElementsAre("logged 2"));
    }
    LogText::Log("logged 3");
    EXPECT_THAT(text_logger1.GetLinesUnsafe(),
                ElementsAre("logged 1", "logged 3"));
}

TEST(ThreadCaptureTest, ThreadsAreNotCrossed) {
  LogText logger;
  LogText::Log("logged 1");

  std::thread worker([] {
        LogText::Log("logged 2");
      });
  worker.join();

  EXPECT_THAT(logger.GetLinesUnsafe(), ElementsAre("logged 1"));
}

TEST(ThreadCrosserTest, WrapCallIsFineWithoutLogger) {
  bool called = false;
  ThreadCrosser::WrapCall([&called] {
      called = true;
      LogText::Log("not logged");
    })();
  EXPECT_TRUE(called);
}

TEST(ThreadCrosserTest, WrapCallWithNullCallbackIsNull) {
  EXPECT_FALSE(ThreadCrosser::WrapCall(nullptr));
  LogText logger;
  EXPECT_FALSE(ThreadCrosser::WrapCall(nullptr));
}

TEST(ThreadCrosserTest, SingleThreadCrossing) {
  LogText logger;
  LogText::Log("logged 1");

  std::thread worker(ThreadCrosser::WrapCall([] {
        LogText::Log("logged 2");
      }));
  worker.join();

  EXPECT_THAT(logger.GetLinesUnsafe(), ElementsAre("logged 1", "logged 2"));
}

TEST(ThreadCrosserTest, MultipleThreadCrossingWithMultipleLoggers) {
  LogText text_logger;
  LogText::Log("logged 1");
  LogValues count_logger;
  LogValues::Count(1);

  std::thread worker(ThreadCrosser::WrapCall([] {
        std::thread worker(ThreadCrosser::WrapCall([] {
              LogText::Log("logged 2");
              LogValues::Count(2);
            }));
        worker.join();
      }));
  worker.join();

  EXPECT_THAT(text_logger.GetLinesUnsafe(),
              ElementsAre("logged 1", "logged 2"));
  EXPECT_THAT(count_logger.GetCountsUnsafe(), ElementsAre(1, 2));
}

TEST(ThreadCrosserTest, MultipleThreadCrossingWithDifferentLoggerScopes) {
  LogText text_logger;

  std::thread worker(ThreadCrosser::WrapCall([] {
        LogValues count_logger;
        std::thread worker(ThreadCrosser::WrapCall([] {
              LogText::Log("logged 1");
              LogValues::Count(1);
            }));
        worker.join();
        EXPECT_THAT(count_logger.GetCountsUnsafe(), ElementsAre(1));
      }));
  worker.join();

  EXPECT_THAT(text_logger.GetLinesUnsafe(), ElementsAre("logged 1"));
}

TEST(ThreadCrosserTest, DifferentLoggersInSameThread) {
  BlockingCallbackQueue queue;

  std::thread worker([&queue] {
        while (true) {
          LogText logger;
          if (!queue.PopAndCall()) {
            break;
          }
          LogText::Log("logged in thread");
          EXPECT_THAT(logger.GetLinesUnsafe(), ElementsAre("logged in thread"));
        }
      });

  LogText logger1;
  queue.Push(ThreadCrosser::WrapCall([] {
        LogText::Log("logged 1");
      }));
  queue.WaitUntilEmpty();
  EXPECT_THAT(logger1.GetLinesUnsafe(), ElementsAre("logged 1"));

  {
    // It's important for the test case that logger2 overrides logger1, i.e.,
    // that they are both in scope at the same time.
    LogText logger2;
    queue.Push(ThreadCrosser::WrapCall([] {
          LogText::Log("logged 2");
        }));
    queue.WaitUntilEmpty();
    EXPECT_THAT(logger2.GetLinesUnsafe(), ElementsAre("logged 2"));
  }

  queue.Push(ThreadCrosser::WrapCall([] {
        LogText::Log("logged 3");
      }));
  queue.WaitUntilEmpty();
  EXPECT_THAT(logger1.GetLinesUnsafe(), ElementsAre("logged 1", "logged 3"));

  queue.Push(nullptr);  // (Causes the thread to exit.)
  worker.join();
}

int main(int argc, char *argv[]) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "random.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "util.h"             // for LogPrint()
#include "utilstrencodings.h" // for GetTime()

#include <stdlib.h>
#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <sys/syscall.h>
#include <linux/random.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LogPrintf("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(vData.data(), nSize, nSize / 100.0);
        memory_cleanse(vData.data(), nSize);
        LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#if defined(WIN32)
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret) {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret) {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) {
        RandFailure();
    }
#elif defined(HAVE_GETENTROPY)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1) {
        RandFailure();
    }
    int have = 0;
    do {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        RandFailure();
    }
}

void GetStrongRandBytes(unsigned char* out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Produce output
    hasher.Finalize(buf);
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

uint32_t insecure_rand_Rz = 11;
uint32_t insecure_rand_Rw = 11;
void seed_insecure_rand(bool fDeterministic)
{
    // The seed values have some unlikely fixed points which we avoid.
    if (fDeterministic) {
        insecure_rand_Rz = insecure_rand_Rw = 11;
    } else {
        uint32_t tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x9068ffffU);
        insecure_rand_Rz = tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x464fffffU);
        insecure_rand_Rw = tmp;
    }
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            if (overwritten[x]) {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}
<commit_msg>random: Add fallback if getrandom syscall not available<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "random.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "util.h"             // for LogPrint()
#include "utilstrencodings.h" // for GetTime()

#include <stdlib.h>
#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <sys/syscall.h>
#include <linux/random.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LogPrintf("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(vData.data(), nSize, nSize / 100.0);
        memory_cleanse(vData.data(), nSize);
        LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
 * compatible way to get cryptographic randomness on UNIX-ish platforms.
 */
void GetDevURandom(unsigned char *ent32)
{
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1) {
        RandFailure();
    }
    int have = 0;
    do {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
}
#endif

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#if defined(WIN32)
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret) {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret) {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
    if (rv != NUM_OS_RANDOM_BYTES) {
        if (rv < 0 && errno == ENOSYS) {
            /* Fallback for kernel <3.17: the return value will be -1 and errno
             * ENOSYS if the syscall is not available, in that case fall back
             * to /dev/urandom.
             */
            GetDevURandom(ent32);
        } else {
            RandFailure();
        }
    }
#elif defined(HAVE_GETENTROPY)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    GetDevURandom(ent32);
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        RandFailure();
    }
}

void GetStrongRandBytes(unsigned char* out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Produce output
    hasher.Finalize(buf);
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

uint32_t insecure_rand_Rz = 11;
uint32_t insecure_rand_Rw = 11;
void seed_insecure_rand(bool fDeterministic)
{
    // The seed values have some unlikely fixed points which we avoid.
    if (fDeterministic) {
        insecure_rand_Rz = insecure_rand_Rw = 11;
    } else {
        uint32_t tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x9068ffffU);
        insecure_rand_Rz = tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x464fffffU);
        insecure_rand_Rw = tmp;
    }
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            if (overwritten[x]) {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}
<|endoftext|>