<commit_before>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/exceptions.h"

#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/object.h"
#include "vm/stack_frame.h"

namespace dart {

DEFINE_FLAG(bool, print_stack_trace_at_throw, false,
    "Prints a stack trace everytime a throw occurs.");

// Iterate through the stack frames and try to find a frame with an
// exception handler. Once found, set the pc, sp and fp so that execution
// can continue in that frame.
static bool FindExceptionHandler(uword* handler_pc,
                                 uword* handler_sp,
                                 uword* handler_fp,
                                 GrowableArray<uword>* stack_frame_pcs) {
  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
  StackFrame* frame = frames.NextFrame();
  ASSERT(frame != NULL);
  while (!frame->IsEntryFrame()) {
    if (frame->IsDartFrame()) {
      stack_frame_pcs->Add(frame->pc());
      DartFrame* dart_frame = reinterpret_cast<DartFrame*>(frame);
      if (dart_frame->FindExceptionHandler(handler_pc)) {
        *handler_sp = frame->sp();
        *handler_fp = frame->fp();
        return true;
      }
    }
    frame = frames.NextFrame();
    ASSERT(frame != NULL);
  }
  ASSERT(frame->IsEntryFrame());
  *handler_pc = frame->pc();
  *handler_sp = frame->sp();
  *handler_fp = frame->fp();
  return false;
}

static void ThrowExceptionHelper(const Instance& exception,
                                 const Instance& existing_stacktrace) {
  uword handler_pc = 0;
  uword handler_sp = 0;
  uword handler_fp = 0;
  GrowableArray<uword> stack_frame_pcs;
  bool handler_exists = FindExceptionHandler(&handler_pc,
                                             &handler_sp,
                                             &handler_fp,
                                             &stack_frame_pcs);
  // TODO(5411263): At some point we can optimize by figuring out if a
  // stack trace is needed based on whether the catch code specifies a
  // stack trace object or there is a rethrow in the catch clause.
  ASSERT(stack_frame_pcs.length() > 0);  // At least one dart frame must exist.
  Stacktrace& stacktrace = Stacktrace::Handle();
  if (existing_stacktrace.IsNull()) {
    stacktrace = Stacktrace::New(stack_frame_pcs);
  } else {
    stacktrace ^= existing_stacktrace.raw();
    stacktrace.Append(stack_frame_pcs);
  }
  if (FLAG_print_stack_trace_at_throw) {
    OS::Print("Exception '%s' thrown:\n", exception.ToCString());
    OS::Print("%s\n", stacktrace.ToCString());
  }
  if (handler_exists) {
    // Found a dart handler for the exception, jump to it.
    CPU::JumpToExceptionHandler(handler_pc,
                                handler_sp,
                                handler_fp,
                                exception,
                                stacktrace);
  } else {
    // No dart exception handler found in this invocation sequence,
    // so we create an unhandled exception object and return to the
    // invocation stub so that it returns this unhandled exception
    // object. The C++ code which invoked this dart sequence can check
    // and do the appropriate thing (rethrow the exception to the
    // dart invocation sequence above it, print diagnostics and terminate
    // the isolate etc.).
    const UnhandledException& unhandled_exception = UnhandledException::Handle(
        UnhandledException::New(exception, stacktrace));
    CPU::JumpToUnhandledExceptionHandler(handler_pc,
                                         handler_sp,
                                         handler_fp,
                                         unhandled_exception);
  }
  UNREACHABLE();
}

void Exceptions::Throw(const Instance& exception) {
  ThrowExceptionHelper(exception, Instance::Handle());
}

void Exceptions::ReThrow(const Instance& exception,
                         const Instance& stacktrace) {
  ASSERT(!exception.IsNull());
  ThrowExceptionHelper(exception, stacktrace);
}

void Exceptions::ThrowByType(
    ExceptionType type, const GrowableArray<const Object*>& arguments) {
  const Instance& exception = Instance::Handle(Create(type, arguments));
  Throw(exception);
}

RawInstance* Exceptions::Create(
    ExceptionType type, const GrowableArray<const Object*>& arguments) {
  String& class_name = String::Handle();
  switch (type) {
    case kIndexOutOfRange:
      class_name = String::NewSymbol("IndexOutOfRangeException");
      break;
    case kIllegalArgument:
      class_name = String::NewSymbol("IllegalArgumentException");
      break;
    case kNoSuchMethod:
      class_name = String::NewSymbol("NoSuchMethodException");
      break;
    case kClosureArgumentMismatch:
      class_name = String::NewSymbol("ClosureArgumentMismatchException");
      break;
    case kObjectNotClosure:
      class_name = String::NewSymbol("ObjectNotClosureException");
      break;
    case kBadNumberFormat:
      class_name = String::NewSymbol("BadNumberFormatException");
      break;
    case kStackOverflow:
      class_name = String::NewSymbol("StackOverflowException");
      break;
    case kWrongArgumentCount:
      class_name = String::NewSymbol("WrongArgumentCountException");
      break;
    case kInternalError:
      class_name = String::NewSymbol("InternalError");
      break;
    case kNullPointer:
      class_name = String::NewSymbol("NullPointerException");
      break;
    case kIllegalJSRegExp:
      class_name = String::NewSymbol("IllegalJSRegExpException");
      break;
  }

  return DartLibraryCalls::ExceptionCreate(class_name, arguments);
}

}  // namespace dart
<commit_msg>Fix assertion during throwing an exception. We could be throwing an exception from a stub frame and not have any dart frames at all, just treat the stack trace as empty in this case and go with an unhandled exception. Review URL: http://codereview.chromium.org//8587041<commit_after>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/exceptions.h"

#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/object.h"
#include "vm/stack_frame.h"

namespace dart {

DEFINE_FLAG(bool, print_stack_trace_at_throw, false,
    "Prints a stack trace everytime a throw occurs.");

// Iterate through the stack frames and try to find a frame with an
// exception handler. Once found, set the pc, sp and fp so that execution
// can continue in that frame.
static bool FindExceptionHandler(uword* handler_pc,
                                 uword* handler_sp,
                                 uword* handler_fp,
                                 GrowableArray<uword>* stack_frame_pcs) {
  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
  StackFrame* frame = frames.NextFrame();
  ASSERT(frame != NULL);
  while (!frame->IsEntryFrame()) {
    if (frame->IsDartFrame()) {
      stack_frame_pcs->Add(frame->pc());
      DartFrame* dart_frame = reinterpret_cast<DartFrame*>(frame);
      if (dart_frame->FindExceptionHandler(handler_pc)) {
        *handler_sp = frame->sp();
        *handler_fp = frame->fp();
        return true;
      }
    }
    frame = frames.NextFrame();
    ASSERT(frame != NULL);
  }
  ASSERT(frame->IsEntryFrame());
  *handler_pc = frame->pc();
  *handler_sp = frame->sp();
  *handler_fp = frame->fp();
  return false;
}

static void ThrowExceptionHelper(const Instance& exception,
                                 const Instance& existing_stacktrace) {
  uword handler_pc = 0;
  uword handler_sp = 0;
  uword handler_fp = 0;
  GrowableArray<uword> stack_frame_pcs;
  bool handler_exists = FindExceptionHandler(&handler_pc,
                                             &handler_sp,
                                             &handler_fp,
                                             &stack_frame_pcs);
  // TODO(5411263): At some point we can optimize by figuring out if a
  // stack trace is needed based on whether the catch code specifies a
  // stack trace object or there is a rethrow in the catch clause.
  Stacktrace& stacktrace = Stacktrace::Handle();
  if (stack_frame_pcs.length() > 0) {
    if (existing_stacktrace.IsNull()) {
      stacktrace = Stacktrace::New(stack_frame_pcs);
    } else {
      stacktrace ^= existing_stacktrace.raw();
      stacktrace.Append(stack_frame_pcs);
    }
  } else {
    stacktrace ^= existing_stacktrace.raw();
  }
  if (FLAG_print_stack_trace_at_throw) {
    OS::Print("Exception '%s' thrown:\n", exception.ToCString());
    OS::Print("%s\n", stacktrace.ToCString());
  }
  if (handler_exists) {
    // Found a dart handler for the exception, jump to it.
    CPU::JumpToExceptionHandler(handler_pc,
                                handler_sp,
                                handler_fp,
                                exception,
                                stacktrace);
  } else {
    // No dart exception handler found in this invocation sequence,
    // so we create an unhandled exception object and return to the
    // invocation stub so that it returns this unhandled exception
    // object. The C++ code which invoked this dart sequence can check
    // and do the appropriate thing (rethrow the exception to the
    // dart invocation sequence above it, print diagnostics and terminate
    // the isolate etc.).
    const UnhandledException& unhandled_exception = UnhandledException::Handle(
        UnhandledException::New(exception, stacktrace));
    CPU::JumpToUnhandledExceptionHandler(handler_pc,
                                         handler_sp,
                                         handler_fp,
                                         unhandled_exception);
  }
  UNREACHABLE();
}

void Exceptions::Throw(const Instance& exception) {
  ThrowExceptionHelper(exception, Instance::Handle());
}

void Exceptions::ReThrow(const Instance& exception,
                         const Instance& stacktrace) {
  ASSERT(!exception.IsNull());
  ThrowExceptionHelper(exception, stacktrace);
}

void Exceptions::ThrowByType(
    ExceptionType type, const GrowableArray<const Object*>& arguments) {
  const Instance& exception = Instance::Handle(Create(type, arguments));
  Throw(exception);
}

RawInstance* Exceptions::Create(
    ExceptionType type, const GrowableArray<const Object*>& arguments) {
  String& class_name = String::Handle();
  switch (type) {
    case kIndexOutOfRange:
      class_name = String::NewSymbol("IndexOutOfRangeException");
      break;
    case kIllegalArgument:
      class_name = String::NewSymbol("IllegalArgumentException");
      break;
    case kNoSuchMethod:
      class_name = String::NewSymbol("NoSuchMethodException");
      break;
    case kClosureArgumentMismatch:
      class_name = String::NewSymbol("ClosureArgumentMismatchException");
      break;
    case kObjectNotClosure:
      class_name = String::NewSymbol("ObjectNotClosureException");
      break;
    case kBadNumberFormat:
      class_name = String::NewSymbol("BadNumberFormatException");
      break;
    case kStackOverflow:
      class_name = String::NewSymbol("StackOverflowException");
      break;
    case kWrongArgumentCount:
      class_name = String::NewSymbol("WrongArgumentCountException");
      break;
    case kInternalError:
      class_name = String::NewSymbol("InternalError");
      break;
    case kNullPointer:
      class_name = String::NewSymbol("NullPointerException");
      break;
    case kIllegalJSRegExp:
      class_name = String::NewSymbol("IllegalJSRegExpException");
      break;
  }

  return DartLibraryCalls::ExceptionCreate(class_name, arguments);
}

}  // namespace dart
<|endoftext|>


<commit_before>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <iostream>
#include <memory>

#include <schwa/config.h>
#include <schwa/dr/config.h>
#include <schwa/tokenizer.h>
#include <schwa/tokenizer/debug_text_stream.h>
#include <schwa/tokenizer/docrep_stream.h>
#include <schwa/tokenizer/text_stream.h>

namespace cf = schwa::config;
namespace dr = schwa::dr;
namespace tok = schwa::tokenizer;

namespace {

class Config : public cf::OpMain {
public:
  cf::IStreamOp input;
  cf::OStreamOp output;
  cf::EnumOp<std::string> printer;
  cf::Op<size_t> input_buffer;
  dr::DocrepOpGroup dr;

  Config(dr::BaseDocSchema &dschema) :
      cf::OpMain("tok", "Schwa-Lab tokenizer"),
      input(*this, "input", "input filename"),
      output(*this, "output", "output filename"),
      printer(*this, "printer", "which printer to use as output", {"text", "debug", "docrep"}, "text"),
      input_buffer(*this, "input_buffer", "input buffer size (bytes)", tok::BUFFER_SIZE),
      dr(*this, dschema)
    { }
  virtual ~Config(void) { }
};

}  // namespace

int
main(int argc, char *argv[]) {
  // instantiate a document schema for use in the config framework
  tok::Doc::Schema schema;

  // parse the command line options
  Config c(schema);
  c.main(argc, argv);

  // input and file files
  std::istream &in = c.input.file();
  std::ostream &out = c.output.file();

  // printer
  std::unique_ptr<tok::Stream> stream;
  if (c.printer() == "text")
    stream = std::unique_ptr<tok::Stream>(new tok::TextStream(out));
  else if (c.printer() == "debug")
    stream = std::unique_ptr<tok::Stream>(new tok::DebugTextStream(out));
  else if (c.printer() == "docrep")
    stream = std::unique_ptr<tok::Stream>(new tok::DocrepStream(out, schema));
  else
    throw cf::ConfigException("Unknown value", "printer", c.printer());

  tok::Tokenizer t;
  t.tokenize_stream(*stream, in, c.input_buffer());

  return 0;
}
<commit_msg>Updated the tokenizer main to be stylistically consistent with the others.<commit_after>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <memory>

#include <schwa/config.h>
#include <schwa/dr/config.h>
#include <schwa/io/logging.h>
#include <schwa/tokenizer.h>
#include <schwa/tokenizer/debug_text_stream.h>
#include <schwa/tokenizer/docrep_stream.h>
#include <schwa/tokenizer/text_stream.h>

namespace cf = schwa::config;
namespace dr = schwa::dr;
namespace io = schwa::io;
namespace tok = schwa::tokenizer;

int
main(int argc, char **argv) {
  // Instantiate a document schema for use in the docrep config framework.
  tok::Doc::Schema schema;

  // Construct an option parser.
  cf::OpMain cfg("tokenizer", "Schwa-Lab tokenizer");
  cf::IStreamOp input(cfg, "input", "The input file");
  cf::OStreamOp output(cfg, "output", "The output file");
  cf::EnumOp<std::string> printer(cfg, "printer", "which printer to use as output", {"text", "debug", "docrep"}, "text");
  cf::Op<size_t> input_buffer(cfg, "input_buffer", "input buffer size (bytes)", tok::BUFFER_SIZE);
  cf::OStreamOp log(cfg, "log", "The file to log to", cf::OStreamOp::STDERR_STRING);
  cf::LogLevelOp log_level(cfg, "log_level", "The level to log at", "info");
  dr::DocrepOpGroup dr(cfg, schema);

  // Parse argv.
  cfg.main(argc, argv);

  // Configure logging.
  io::default_logger = new io::PrettyLogger(log.file());
  io::default_logger->threshold(log_level());

  // Configure the tokenizer printer.
  std::unique_ptr<tok::Stream> stream;
  if (printer() == "text")
    stream.reset(new tok::TextStream(output.file()));
  else if (printer() == "debug")
    stream.reset(new tok::DebugTextStream(output.file()));
  else if (printer() == "docrep")
    stream.reset(new tok::DocrepStream(output.file(), schema));
  else
    throw cf::ConfigException("Unknown value", "printer", printer());

  // Construct the tokenizer and tokenize the input.
  tok::Tokenizer t;
  const bool success = t.tokenize_stream(*stream, input.file(), input_buffer());
  return success ? 0 : 1;
}
<|endoftext|>


<commit_before><commit_msg>Add more checks to be able to isolate why chrome cannot do a GetProcAddress of NtCreateFile.<commit_after><|endoftext|>


<commit_before>/*
 * GameKeeper Framework
 *
 * Copyright (C) 2013 Karol Herbst <gamekeeper@karolherbst.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <gamekeeper/backend/libsecretmanager.h>
#include <gamekeeper/utils/stringutils.h>

#include <libsecret/secret.h>

GAMEKEEPER_NAMESPACE_START(backend)

#define GPOINTER_CAST(value) const_cast<gpointer>(static_cast<const void *>(value))

static constexpr char GK_TOKEN_SCHEMA_NAME[] = "org.gamekeeper.authmanager.libsecret.token";

static constexpr char GK_TOKEN_GROUP[] = "group";
static constexpr char GK_TOKEN_KEY[] = "key";
static constexpr char GK_TOKEN_EXPIRY[] = "expiry";
static constexpr char GK_TOKEN_APPLICATION[] = "application";
static constexpr char GK_TOKEN_APPLICATION_VALUE[] = "gamekeeper";

static SecretSchema GK_TOKEN_SCHEMA_TEMPLATE
{
	.name = GK_TOKEN_SCHEMA_NAME,
	.flags = SECRET_SCHEMA_NONE,
	.attributes =
	{
		{
			.name = GK_TOKEN_GROUP,
			.type = SECRET_SCHEMA_ATTRIBUTE_STRING
		},
		{
			.name = GK_TOKEN_KEY,
			.type = SECRET_SCHEMA_ATTRIBUTE_STRING
		},
		{
			.name = GK_TOKEN_EXPIRY,
			.type = SECRET_SCHEMA_ATTRIBUTE_INTEGER
		},
		// always gamekeeper
		{
			.name = GK_TOKEN_APPLICATION,
			.type = SECRET_SCHEMA_ATTRIBUTE_STRING
		},
		{
			.name = nullptr
		}
	}
};

void
LibSecretManager::saveToken(const AuthManager::Token & token)
{
	SecretSchema genSchema = GK_TOKEN_SCHEMA_TEMPLATE;
	GHashTable * attributes = g_hash_table_new(&g_direct_hash, &g_direct_equal);

	// save trivial stuff first
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_GROUP), GPOINTER_CAST(token.group.c_str()));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_KEY), GPOINTER_CAST(token.key.c_str()));
	std::string expiryStr(utils::String::toString(std::chrono::duration_cast<std::chrono::seconds>(token.expiry.time_since_epoch()).count()));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_EXPIRY), GPOINTER_CAST(expiryStr.c_str()));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_APPLICATION), GPOINTER_CAST(GK_TOKEN_APPLICATION_VALUE));

	// we begin at the fourth attribute
	uint8_t i = 4;
	for(const auto & p : token.properties)
	{
		genSchema.attributes[i].name = p.first.c_str();
		genSchema.attributes[i].type = SECRET_SCHEMA_ATTRIBUTE_STRING;
		g_hash_table_insert(attributes, GPOINTER_CAST(p.first.c_str()), GPOINTER_CAST(p.second.c_str()));
		i++;
	}
	genSchema.attributes[i].name = nullptr;

	secret_password_storev_sync(&genSchema, attributes, nullptr, (std::string("gamekeeper token for: ") + token.group).c_str(), token.value.c_str(), nullptr, nullptr);

	g_hash_table_destroy(attributes);
}

AuthManager::Tokens
LibSecretManager::readAllTokens(const std::string & group)
{
	AuthManager::Tokens tokens;
	GHashTable * attributes = g_hash_table_new(&g_str_hash, &g_str_equal);

	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_APPLICATION), GPOINTER_CAST(GK_TOKEN_APPLICATION_VALUE));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_GROUP), GPOINTER_CAST(group.c_str()));

	GList * list = secret_service_search_sync(nullptr, nullptr, attributes, static_cast<SecretSearchFlags>(SECRET_SEARCH_ALL | SECRET_SEARCH_LOAD_SECRETS), nullptr, nullptr);
	g_hash_table_destroy(attributes);

	GList * it = list;
	while(it)
	{
		SecretItem * item = static_cast<SecretItem *>(it->data);
		SecretValue * value = secret_item_get_secret(item);
		GHashTable * atts = secret_item_get_attributes(item);
		gsize * secretSize;

		AuthManager::Token token(static_cast<gchar *>(g_hash_table_lookup(atts, GK_TOKEN_KEY)),
		                         secret_value_get_text(value),
		                         group,
		                         utils::String::toType<AuthManager::Token::TimePoint::rep>(static_cast<gchar *>(g_hash_table_lookup(atts, GK_TOKEN_EXPIRY))));

		g_hash_table_foreach(atts, [](gpointer keyPtr, gpointer valuePtr, gpointer tokenPtr)
		{
			gchar * key = static_cast<gchar *>(keyPtr);
			gchar * value = static_cast<gchar *>(valuePtr);
			AuthManager::Token * token = static_cast<AuthManager::Token *>(tokenPtr);

			// key and expiry are a special cases
			if(std::string(GK_TOKEN_KEY) != key && std::string(GK_TOKEN_EXPIRY) != key)
			{
				token->properties.insert(std::make_pair(key, value));
			}
		}, &token);

		it = it->next;

		g_hash_table_unref(atts);
		secret_value_unref(value);
		tokens.push_back(std::move(token));
	}

	g_list_free(list);

	return tokens;
}

GAMEKEEPER_NAMESPACE_END(backend)
<commit_msg>backend/libsecretmanager: convert while loop into a for loop<commit_after>/*
 * GameKeeper Framework
 *
 * Copyright (C) 2013 Karol Herbst <gamekeeper@karolherbst.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <gamekeeper/backend/libsecretmanager.h>
#include <gamekeeper/utils/stringutils.h>

#include <libsecret/secret.h>

GAMEKEEPER_NAMESPACE_START(backend)

#define GPOINTER_CAST(value) const_cast<gpointer>(static_cast<const void *>(value))

static constexpr char GK_TOKEN_SCHEMA_NAME[] = "org.gamekeeper.authmanager.libsecret.token";

static constexpr char GK_TOKEN_GROUP[] = "group";
static constexpr char GK_TOKEN_KEY[] = "key";
static constexpr char GK_TOKEN_EXPIRY[] = "expiry";
static constexpr char GK_TOKEN_APPLICATION[] = "application";
static constexpr char GK_TOKEN_APPLICATION_VALUE[] = "gamekeeper";

static SecretSchema GK_TOKEN_SCHEMA_TEMPLATE
{
	.name = GK_TOKEN_SCHEMA_NAME,
	.flags = SECRET_SCHEMA_NONE,
	.attributes =
	{
		{
			.name = GK_TOKEN_GROUP,
			.type = SECRET_SCHEMA_ATTRIBUTE_STRING
		},
		{
			.name = GK_TOKEN_KEY,
			.type = SECRET_SCHEMA_ATTRIBUTE_STRING
		},
		{
			.name = GK_TOKEN_EXPIRY,
			.type = SECRET_SCHEMA_ATTRIBUTE_INTEGER
		},
		// always gamekeeper
		{
			.name = GK_TOKEN_APPLICATION,
			.type = SECRET_SCHEMA_ATTRIBUTE_STRING
		},
		{
			.name = nullptr
		}
	}
};

void
LibSecretManager::saveToken(const AuthManager::Token & token)
{
	SecretSchema genSchema = GK_TOKEN_SCHEMA_TEMPLATE;
	GHashTable * attributes = g_hash_table_new(&g_direct_hash, &g_direct_equal);

	// save trivial stuff first
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_GROUP), GPOINTER_CAST(token.group.c_str()));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_KEY), GPOINTER_CAST(token.key.c_str()));
	std::string expiryStr(utils::String::toString(std::chrono::duration_cast<std::chrono::seconds>(token.expiry.time_since_epoch()).count()));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_EXPIRY), GPOINTER_CAST(expiryStr.c_str()));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_APPLICATION), GPOINTER_CAST(GK_TOKEN_APPLICATION_VALUE));

	// we begin at the fourth attribute
	uint8_t i = 4;
	for(const auto & p : token.properties)
	{
		genSchema.attributes[i].name = p.first.c_str();
		genSchema.attributes[i].type = SECRET_SCHEMA_ATTRIBUTE_STRING;
		g_hash_table_insert(attributes, GPOINTER_CAST(p.first.c_str()), GPOINTER_CAST(p.second.c_str()));
		i++;
	}
	genSchema.attributes[i].name = nullptr;

	secret_password_storev_sync(&genSchema, attributes, nullptr, (std::string("gamekeeper token for: ") + token.group).c_str(), token.value.c_str(), nullptr, nullptr);

	g_hash_table_destroy(attributes);
}

AuthManager::Tokens
LibSecretManager::readAllTokens(const std::string & group)
{
	AuthManager::Tokens tokens;
	GHashTable * attributes = g_hash_table_new(&g_str_hash, &g_str_equal);

	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_APPLICATION), GPOINTER_CAST(GK_TOKEN_APPLICATION_VALUE));
	g_hash_table_insert(attributes, GPOINTER_CAST(GK_TOKEN_GROUP), GPOINTER_CAST(group.c_str()));

	GList * list = secret_service_search_sync(nullptr, nullptr, attributes, static_cast<SecretSearchFlags>(SECRET_SEARCH_ALL | SECRET_SEARCH_LOAD_SECRETS), nullptr, nullptr);
	g_hash_table_destroy(attributes);

	for(GList * it = list; it != nullptr; it = it->next)
	{
		SecretItem * item = static_cast<SecretItem *>(it->data);
		SecretValue * value = secret_item_get_secret(item);
		GHashTable * atts = secret_item_get_attributes(item);
		gsize * secretSize;

		AuthManager::Token token(static_cast<gchar *>(g_hash_table_lookup(atts, GK_TOKEN_KEY)),
		                         secret_value_get_text(value),
		                         group,
		                         utils::String::toType<AuthManager::Token::TimePoint::rep>(static_cast<gchar *>(g_hash_table_lookup(atts, GK_TOKEN_EXPIRY))));

		g_hash_table_foreach(atts, [](gpointer keyPtr, gpointer valuePtr, gpointer tokenPtr)
		{
			gchar * key = static_cast<gchar *>(keyPtr);
			gchar * value = static_cast<gchar *>(valuePtr);
			AuthManager::Token * token = static_cast<AuthManager::Token *>(tokenPtr);

			// key and expiry are a special cases
			if(std::string(GK_TOKEN_KEY) != key && std::string(GK_TOKEN_EXPIRY) != key)
			{
				token->properties.insert(std::make_pair(key, value));
			}
		}, &token);

		g_hash_table_unref(atts);
		secret_value_unref(value);
		tokens.push_back(std::move(token));
	}

	g_list_free(list);

	return tokens;
}

GAMEKEEPER_NAMESPACE_END(backend)
<|endoftext|>


<commit_before>#include "buffer_cache/co_functions.hpp"
#include "concurrency/promise.hpp"

struct co_block_available_callback_t : public block_available_callback_t {
    coro_t *self;
    buf_t *value;

    virtual void on_block_available(buf_t *block) {
        value = block;
        self->notify();
    }

    buf_t *join() {
        self = coro_t::self();
        coro_t::wait();
        return value;
    }
};

buf_t *co_acquire_block(const thread_saver_t& saver, transaction_t *transaction, block_id_t block_id, access_t mode, threadsafe_cond_t *acquisition_cond) {
    transaction->ensure_thread(saver);
    co_block_available_callback_t cb;
    buf_t *value = transaction->acquire(block_id, mode, &cb);
    if (acquisition_cond) {
        // TODO: This is worthless crap, because the
        // transaction_t::acquire interface is a lie.
        acquisition_cond->pulse();
    }
    if (!value) {
        value = cb.join();
    }
    rassert(value);
    return value;
}

struct large_value_acquired_t : public large_buf_available_callback_t {
    coro_t *self;
    large_value_acquired_t() : self(coro_t::self()) { }
    void on_large_buf_available(UNUSED large_buf_t *large_value) { self->notify(); }
};

void co_acquire_large_buf_for_unprepend(const thread_saver_t& saver, large_buf_t *lb, int64_t length) {
    large_value_acquired_t acquired;
    lb->ensure_thread(saver);
    lb->acquire_for_unprepend(length, &acquired);
    coro_t::wait();
}

void co_acquire_large_buf_slice(const thread_saver_t& saver, large_buf_t *lb, int64_t offset, int64_t size, threadsafe_cond_t *acquisition_cond) {
    large_value_acquired_t acquired;
    lb->ensure_thread(saver);
    lb->acquire_slice(offset, size, &acquired);
    if (acquisition_cond) {
        // TODO: This is worthless crap, because the
        // transaction_t::acquire interface is a lie.
        acquisition_cond->pulse();
    }
    coro_t::wait();
}

void co_acquire_large_buf(const thread_saver_t& saver, large_buf_t *lb, threadsafe_cond_t *acquisition_cond) {
    co_acquire_large_buf_slice(saver, lb, 0, lb->root_ref->size, acquisition_cond);
}

void co_acquire_large_buf_lhs(const thread_saver_t& saver, large_buf_t *lb) {
    co_acquire_large_buf_slice(saver, lb, 0, std::min(1L, lb->root_ref->size));
}

void co_acquire_large_buf_rhs(const thread_saver_t& saver, large_buf_t *lb) {
    int64_t beg = std::max(int64_t(0), lb->root_ref->size - 1);
    co_acquire_large_buf_slice(saver, lb, beg, lb->root_ref->size - beg);
}

void co_acquire_large_buf_for_delete(large_buf_t *large_value) {
    large_value_acquired_t acquired;
    large_value->acquire_for_delete(&acquired);
    coro_t::wait();
}

// Well this is repetitive.
struct transaction_begun_callback_t : public transaction_begin_callback_t {
    flat_promise_t<transaction_t*> txn;

    void on_txn_begin(transaction_t *txn_) {
        txn.pulse(txn_);
    }

    transaction_t *join() {
        return txn.wait();
    }
};

transaction_t *co_begin_transaction(const thread_saver_t& saver, cache_t *cache, access_t access, int expected_change_count, repli_timestamp recency_timestamp, order_token_t token) {
    rassert(recency_timestamp.time != repli_timestamp::invalid.time || is_read_mode(access));

    // TODO: ensure_thread is retarded.
    cache->assert_thread();  // temporary check
    cache->ensure_thread(saver);
    transaction_begun_callback_t cb;
    transaction_t *value = cache->begin_transaction(token, access, expected_change_count, recency_timestamp, &cb);
    if (!value) {
        value = cb.join();
    }
    rassert(value);
    return value;
}

struct transaction_committed_t : public transaction_commit_callback_t {
    coro_t *self;
    transaction_committed_t() : self(coro_t::self()) { }
    void on_txn_commit(UNUSED transaction_t *transaction) {
        self->notify();
    }
};

void co_commit_transaction(const thread_saver_t& saver, transaction_t *transaction) {
    transaction->ensure_thread(saver);
    transaction_committed_t cb;
    if (!transaction->commit(&cb)) {
        coro_t::wait();
    }
}

void co_get_subtree_recencies(transaction_t *txn, block_id_t *block_ids, size_t num_block_ids, repli_timestamp *recencies_out) {
    struct : public get_subtree_recencies_callback_t {
        void got_subtree_recencies() { cond.pulse(); }
        cond_t cond;
    } cb;

    txn->get_subtree_recencies(block_ids, num_block_ids, recencies_out, &cb);

    cb.cond.wait();
}
<commit_msg>Remove a wrong assertion<commit_after>#include "buffer_cache/co_functions.hpp"
#include "concurrency/promise.hpp"

struct co_block_available_callback_t : public block_available_callback_t {
    coro_t *self;
    buf_t *value;

    virtual void on_block_available(buf_t *block) {
        value = block;
        self->notify();
    }

    buf_t *join() {
        self = coro_t::self();
        coro_t::wait();
        return value;
    }
};

buf_t *co_acquire_block(const thread_saver_t& saver, transaction_t *transaction, block_id_t block_id, access_t mode, threadsafe_cond_t *acquisition_cond) {
    transaction->ensure_thread(saver);
    co_block_available_callback_t cb;
    buf_t *value = transaction->acquire(block_id, mode, &cb);
    if (acquisition_cond) {
        // TODO: This is worthless crap, because the
        // transaction_t::acquire interface is a lie.
        acquisition_cond->pulse();
    }
    if (!value) {
        value = cb.join();
    }
    rassert(value);
    return value;
}

struct large_value_acquired_t : public large_buf_available_callback_t {
    coro_t *self;
    large_value_acquired_t() : self(coro_t::self()) { }
    void on_large_buf_available(UNUSED large_buf_t *large_value) { self->notify(); }
};

void co_acquire_large_buf_for_unprepend(const thread_saver_t& saver, large_buf_t *lb, int64_t length) {
    large_value_acquired_t acquired;
    lb->ensure_thread(saver);
    lb->acquire_for_unprepend(length, &acquired);
    coro_t::wait();
}

void co_acquire_large_buf_slice(const thread_saver_t& saver, large_buf_t *lb, int64_t offset, int64_t size, threadsafe_cond_t *acquisition_cond) {
    large_value_acquired_t acquired;
    lb->ensure_thread(saver);
    lb->acquire_slice(offset, size, &acquired);
    if (acquisition_cond) {
        // TODO: This is worthless crap, because the
        // transaction_t::acquire interface is a lie.
        acquisition_cond->pulse();
    }
    coro_t::wait();
}

void co_acquire_large_buf(const thread_saver_t& saver, large_buf_t *lb, threadsafe_cond_t *acquisition_cond) {
    co_acquire_large_buf_slice(saver, lb, 0, lb->root_ref->size, acquisition_cond);
}

void co_acquire_large_buf_lhs(const thread_saver_t& saver, large_buf_t *lb) {
    co_acquire_large_buf_slice(saver, lb, 0, std::min(1L, lb->root_ref->size));
}

void co_acquire_large_buf_rhs(const thread_saver_t& saver, large_buf_t *lb) {
    int64_t beg = std::max(int64_t(0), lb->root_ref->size - 1);
    co_acquire_large_buf_slice(saver, lb, beg, lb->root_ref->size - beg);
}

void co_acquire_large_buf_for_delete(large_buf_t *large_value) {
    large_value_acquired_t acquired;
    large_value->acquire_for_delete(&acquired);
    coro_t::wait();
}

// Well this is repetitive.
struct transaction_begun_callback_t : public transaction_begin_callback_t {
    flat_promise_t<transaction_t*> txn;

    void on_txn_begin(transaction_t *txn_) {
        txn.pulse(txn_);
    }

    transaction_t *join() {
        return txn.wait();
    }
};

transaction_t *co_begin_transaction(const thread_saver_t& saver, cache_t *cache, access_t access, int expected_change_count, repli_timestamp recency_timestamp, order_token_t token) {

    // TODO: ensure_thread is retarded.
    cache->assert_thread();  // temporary check
    cache->ensure_thread(saver);
    transaction_begun_callback_t cb;
    transaction_t *value = cache->begin_transaction(token, access, expected_change_count, recency_timestamp, &cb);
    if (!value) {
        value = cb.join();
    }
    rassert(value);
    return value;
}

struct transaction_committed_t : public transaction_commit_callback_t {
    coro_t *self;
    transaction_committed_t() : self(coro_t::self()) { }
    void on_txn_commit(UNUSED transaction_t *transaction) {
        self->notify();
    }
};

void co_commit_transaction(const thread_saver_t& saver, transaction_t *transaction) {
    transaction->ensure_thread(saver);
    transaction_committed_t cb;
    if (!transaction->commit(&cb)) {
        coro_t::wait();
    }
}

void co_get_subtree_recencies(transaction_t *txn, block_id_t *block_ids, size_t num_block_ids, repli_timestamp *recencies_out) {
    struct : public get_subtree_recencies_callback_t {
        void got_subtree_recencies() { cond.pulse(); }
        cond_t cond;
    } cb;

    txn->get_subtree_recencies(block_ids, num_block_ids, recencies_out, &cb);

    cb.cond.wait();
}
<|endoftext|>


<commit_before>/* Copyright 2000-2004 Ryan Bloom
 *
 * 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.
 *
 * Portions of this file were taken from testall.c in the APR test suite,
 * written by members of the Apache Software Foundation.
 */

#include "abts.h"
#include "abts_tests.h"
#include "testutil.h"

#define ABTS_STAT_SIZE 6
static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'};
static int curr_char;
static int verbose = 0;
static int exclude = 0;
static int quiet = 0;
static int list_tests = 0;

const char **testlist = NULL;
//  defined in logunit.cpp
abts_suite* abts_run_suites(abts_suite*);

static int find_test_name(const char *testname) {
    int i;
    for (i = 0; testlist[i] != NULL; i++) {
        if (!strcmp(testlist[i], testname)) {
            return 1;
        }
    }
    return 0;
}

/* Determine if the test should be run at all */
static int should_test_run(const char *testname) {
    int found = 0;
    if (list_tests == 1) {
        return 0;
    }
    if (testlist == NULL) {
        return 1;
    }
    found = find_test_name(testname);
    if ((found && !exclude) || (!found && exclude)) {
        return 1;
    }
    return 0;
}

static void reset_status(void)
{
    curr_char = 0;
}

static void update_status(void)
{
    if (!quiet) {
        curr_char = (curr_char + 1) % ABTS_STAT_SIZE;
        fprintf(stdout, "\b%c", status[curr_char]);
        fflush(stdout);
    }
}

static void end_suite(abts_suite *suite)
{
    if (suite != NULL) {
        sub_suite *last = suite->tail;
        if (!quiet) {
            fprintf(stdout, "\b");
            fflush(stdout);
        }
        if (last->failed == 0) {
            fprintf(stdout, "SUCCESS\n");
            fflush(stdout);
        }
        else {
            fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test);
            fflush(stdout);
        }
    }
}

abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full)
{
    sub_suite *subsuite;
    const char *p;
    const char *suite_name;
    curr_char = 0;

    /* Only end the suite if we actually ran it */
    if (suite && suite->tail &&!suite->tail->not_run) {
        end_suite(suite);
    }

    subsuite = (sub_suite*) malloc(sizeof(*subsuite));
    subsuite->num_test = 0;
    subsuite->failed = 0;
    subsuite->next = NULL;
    /* suite_name_full may be an absolute path depending on __FILE__
     * expansion */
    suite_name = strrchr(suite_name_full, '/');
    if (suite_name) {
        suite_name++;
    } else {
        suite_name = suite_name_full;
    }
    p = strrchr(suite_name, '.');
    if (p) {
        subsuite->name = (const char*) memcpy(calloc(p - suite_name + 1, 1),
                                suite_name, p - suite_name);
    }
    else {
        subsuite->name = suite_name;
    }

    if (list_tests) {
        fprintf(stdout, "%s\n", subsuite->name);
    }

    subsuite->not_run = 0;

    if (suite == NULL) {
        suite = (abts_suite*) malloc(sizeof(*suite));
        suite->head = subsuite;
        suite->tail = subsuite;
    }
    else {
        suite->tail->next = subsuite;
        suite->tail = subsuite;
    }

    if (!should_test_run(subsuite->name)) {
        subsuite->not_run = 1;
        return suite;
    }

    reset_status();
    fprintf(stdout, "%-20s:  ", subsuite->name);
    update_status();
    fflush(stdout);

    return suite;
}

void abts_run_test(abts_suite *ts, test_func f, void *value)
{
    abts_case tc;
    sub_suite *ss;

    if (!should_test_run(ts->tail->name)) {
        return;
    }
    ss = ts->tail;

    tc.failed = 0;
    tc.suite = ss;

    ss->num_test++;
    update_status();

    f(&tc, value);

    if (tc.failed) {
        ss->failed++;
    }
}

static int report(abts_suite *suite)
{
    int count = 0;
    sub_suite *dptr;

    if (suite && suite->tail &&!suite->tail->not_run) {
        end_suite(suite);
    }

    for (dptr = suite->head; dptr; dptr = dptr->next) {
        count += dptr->failed;
    }

    if (list_tests) {
        return 0;
    }

    if (count == 0) {
        printf("All tests passed.\n");
        return 0;
    }

    dptr = suite->head;
    fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests");
    fprintf(stdout, "===================================================\n");
    while (dptr != NULL) {
        if (dptr->failed != 0) {
            float percent = ((float)dptr->failed / (float)dptr->num_test);
            fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name,
                    dptr->num_test, dptr->failed, percent * 100);
        }
        dptr = dptr->next;
    }
    return 1;
}

void abts_log_message(const char *fmt, ...)
{
    va_list args;
    update_status();

    if (verbose) {
        va_start(args, fmt);
        vfprintf(stderr, fmt, args);
        va_end(args);
        fprintf(stderr, "\n");
        fflush(stderr);
    }
}

void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected == actual) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected != actual) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected == actual) return;

    tc->failed = TRUE;
    if (verbose) {
        /* Note that the comparison is type-exact, reporting must be a best-fit */
        fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno,
                (unsigned long)expected, (unsigned long)actual);
        fflush(stderr);
    }
}

void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (!expected && !actual) return;
    if (expected && actual)
        if (!strcmp(expected, actual)) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
                       size_t n, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (!strncmp(expected, actual, n)) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (ptr != NULL) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr);
        fflush(stderr);
    }
}

void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected == actual) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_fail(abts_case *tc, const char *message, int lineno)
{
    update_status();
    if (tc->failed) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: %s\n", lineno, message);
        fflush(stderr);
    }
}

void abts_assert(abts_case *tc, const char *message, int condition, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (condition) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: %s\n", lineno, message);
        fflush(stderr);
    }
}

void abts_true(abts_case *tc, int condition, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (condition) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno);
        fflush(stderr);
    }
}

void abts_not_impl(abts_case *tc, const char *message, int lineno)
{
    update_status();

    tc->suite->not_impl++;
    if (verbose) {
        fprintf(stderr, "Line %d: %s\n", lineno, message);
        fflush(stderr);
    }
}

int main(int argc, const char *const argv[]) {
    int i;
    int rv;
    int list_provided = 0;
    abts_suite *suite = NULL;

    initialize();

#if defined(_MSC_VER)
   quiet = 1;
#else
    quiet = !isatty(STDOUT_FILENO);
#endif

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-v")) {
            verbose = 1;
            continue;
        }
        if (!strcmp(argv[i], "-x")) {
            exclude = 1;
            continue;
        }
        if (!strcmp(argv[i], "-l")) {
            list_tests = 1;
            continue;
        }
        if (!strcmp(argv[i], "-q")) {
            quiet = 1;
            continue;
        }
        if (argv[i][0] == '-') {
            fprintf(stderr, "Invalid option: `%s'\n", argv[i]);
            exit(1);
        }
        list_provided = 1;
    }

    if (list_provided) {
        /* Waste a little space here, because it is easier than counting the
         * number of tests listed.  Besides it is at most three char *.
         */
        testlist = (const char**) calloc(argc + 1, sizeof(char *));
        for (i = 1; i < argc; i++) {
            testlist[i - 1] = argv[i];
        }
    }

    suite = abts_run_suites(suite);

    if (suite == 0) {
        fputs("No tests selected\n", stderr);
    } else {
        rv = report(suite);
    }
    return rv;
}
<commit_msg>LOGCXX-220: Reclaim memory allocated for test suite<commit_after>/* Copyright 2000-2004 Ryan Bloom
 *
 * 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.
 *
 * Portions of this file were taken from testall.c in the APR test suite,
 * written by members of the Apache Software Foundation.
 */

#include "abts.h"
#include "abts_tests.h"
#include "testutil.h"

#define ABTS_STAT_SIZE 6
static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'};
static int curr_char;
static int verbose = 0;
static int exclude = 0;
static int quiet = 0;
static int list_tests = 0;

const char **testlist = NULL;
//  defined in logunit.cpp
abts_suite* abts_run_suites(abts_suite*);

static int find_test_name(const char *testname) {
    int i;
    for (i = 0; testlist[i] != NULL; i++) {
        if (!strcmp(testlist[i], testname)) {
            return 1;
        }
    }
    return 0;
}

/* Determine if the test should be run at all */
static int should_test_run(const char *testname) {
    int found = 0;
    if (list_tests == 1) {
        return 0;
    }
    if (testlist == NULL) {
        return 1;
    }
    found = find_test_name(testname);
    if ((found && !exclude) || (!found && exclude)) {
        return 1;
    }
    return 0;
}

static void reset_status(void)
{
    curr_char = 0;
}

static void update_status(void)
{
    if (!quiet) {
        curr_char = (curr_char + 1) % ABTS_STAT_SIZE;
        fprintf(stdout, "\b%c", status[curr_char]);
        fflush(stdout);
    }
}

static void end_suite(abts_suite *suite)
{
    if (suite != NULL) {
        sub_suite *last = suite->tail;
        if (!quiet) {
            fprintf(stdout, "\b");
            fflush(stdout);
        }
        if (last->failed == 0) {
            fprintf(stdout, "SUCCESS\n");
            fflush(stdout);
        }
        else {
            fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test);
            fflush(stdout);
        }
    }
}

abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full)
{
    sub_suite *subsuite;
    const char *p;
    const char *suite_name;
    curr_char = 0;

    /* Only end the suite if we actually ran it */
    if (suite && suite->tail &&!suite->tail->not_run) {
        end_suite(suite);
    }

    subsuite = (sub_suite*) malloc(sizeof(*subsuite));
    subsuite->num_test = 0;
    subsuite->failed = 0;
    subsuite->next = NULL;
    /* suite_name_full may be an absolute path depending on __FILE__
     * expansion */
    suite_name = strrchr(suite_name_full, '/');
    if (suite_name) {
        suite_name++;
    } else {
        suite_name = suite_name_full;
    }
    p = strrchr(suite_name, '.');
    if (p) {
        subsuite->name = (const char*) memcpy(calloc(p - suite_name + 1, 1),
                                suite_name, p - suite_name);
    }
    else {
        subsuite->name = suite_name;
    }

    if (list_tests) {
        fprintf(stdout, "%s\n", subsuite->name);
    }

    subsuite->not_run = 0;

    if (suite == NULL) {
        suite = (abts_suite*) malloc(sizeof(*suite));
        suite->head = subsuite;
        suite->tail = subsuite;
    }
    else {
        suite->tail->next = subsuite;
        suite->tail = subsuite;
    }

    if (!should_test_run(subsuite->name)) {
        subsuite->not_run = 1;
        return suite;
    }

    reset_status();
    fprintf(stdout, "%-20s:  ", subsuite->name);
    update_status();
    fflush(stdout);

    return suite;
}

void abts_run_test(abts_suite *ts, test_func f, void *value)
{
    abts_case tc;
    sub_suite *ss;

    if (!should_test_run(ts->tail->name)) {
        return;
    }
    ss = ts->tail;

    tc.failed = 0;
    tc.suite = ss;

    ss->num_test++;
    update_status();

    f(&tc, value);

    if (tc.failed) {
        ss->failed++;
    }
}

static int report(abts_suite *suite)
{
    int count = 0;
    sub_suite *dptr;

    if (suite && suite->tail &&!suite->tail->not_run) {
        end_suite(suite);
    }

    for (dptr = suite->head; dptr; dptr = dptr->next) {
        count += dptr->failed;
    }

    if (list_tests) {
        return 0;
    }

    if (count == 0) {
        printf("All tests passed.\n");
        return 0;
    }

    dptr = suite->head;
    fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests");
    fprintf(stdout, "===================================================\n");
    while (dptr != NULL) {
        if (dptr->failed != 0) {
            float percent = ((float)dptr->failed / (float)dptr->num_test);
            fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name,
                    dptr->num_test, dptr->failed, percent * 100);
        }
        dptr = dptr->next;
    }
    return 1;
}

void abts_log_message(const char *fmt, ...)
{
    va_list args;
    update_status();

    if (verbose) {
        va_start(args, fmt);
        vfprintf(stderr, fmt, args);
        va_end(args);
        fprintf(stderr, "\n");
        fflush(stderr);
    }
}

void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected == actual) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected != actual) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected == actual) return;

    tc->failed = TRUE;
    if (verbose) {
        /* Note that the comparison is type-exact, reporting must be a best-fit */
        fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno,
                (unsigned long)expected, (unsigned long)actual);
        fflush(stderr);
    }
}

void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (!expected && !actual) return;
    if (expected && actual)
        if (!strcmp(expected, actual)) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
                       size_t n, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (!strncmp(expected, actual, n)) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (ptr != NULL) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr);
        fflush(stderr);
    }
}

void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (expected == actual) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual);
        fflush(stderr);
    }
}

void abts_fail(abts_case *tc, const char *message, int lineno)
{
    update_status();
    if (tc->failed) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: %s\n", lineno, message);
        fflush(stderr);
    }
}

void abts_assert(abts_case *tc, const char *message, int condition, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (condition) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: %s\n", lineno, message);
        fflush(stderr);
    }
}

void abts_true(abts_case *tc, int condition, int lineno)
{
    update_status();
    if (tc->failed) return;

    if (condition) return;

    tc->failed = TRUE;
    if (verbose) {
        fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno);
        fflush(stderr);
    }
}

void abts_not_impl(abts_case *tc, const char *message, int lineno)
{
    update_status();

    tc->suite->not_impl++;
    if (verbose) {
        fprintf(stderr, "Line %d: %s\n", lineno, message);
        fflush(stderr);
    }
}

int main(int argc, const char *const argv[]) {
    int i;
    int rv;
    int list_provided = 0;
    abts_suite *suite = NULL;

    initialize();

#if defined(_MSC_VER)
   quiet = 1;
#else
    quiet = !isatty(STDOUT_FILENO);
#endif

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-v")) {
            verbose = 1;
            continue;
        }
        if (!strcmp(argv[i], "-x")) {
            exclude = 1;
            continue;
        }
        if (!strcmp(argv[i], "-l")) {
            list_tests = 1;
            continue;
        }
        if (!strcmp(argv[i], "-q")) {
            quiet = 1;
            continue;
        }
        if (argv[i][0] == '-') {
            fprintf(stderr, "Invalid option: `%s'\n", argv[i]);
            exit(1);
        }
        list_provided = 1;
    }

    if (list_provided) {
        /* Waste a little space here, because it is easier than counting the
         * number of tests listed.  Besides it is at most three char *.
         */
        testlist = (const char**) calloc(argc + 1, sizeof(char *));
        for (i = 1; i < argc; i++) {
            testlist[i - 1] = argv[i];
        }
    }

    suite = abts_run_suites(suite);

    if (suite == 0) {
        fputs("No tests selected\n", stderr);
    } else {
        rv = report(suite);
        //
        //    clean up suite
        //
        sub_suite* next;
        for(sub_suite* head = suite->head; head != NULL; head = next) {
	   next = head->next;
           free((void*) head->name);
	   free(head);
         }
         free(suite);
    }
    return rv;
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 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 <base58.h>
#include <chainparamsbase.h>
#include <core_io.h>
#include <interfaces/chain.h>
#include <key.h>
#include <key_io.h>
#include <node/context.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <psbt.h>
#include <rpc/blockchain.h>
#include <rpc/client.h>
#include <rpc/request.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <span.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <tinyformat.h>
#include <univalue.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/time.h>

#include <cstdint>
#include <iostream>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>

namespace {
struct RPCFuzzTestingSetup : public TestingSetup {
    RPCFuzzTestingSetup(const std::string& chain_name, const std::vector<const char*>& extra_args) : TestingSetup{chain_name, extra_args}
    {
    }

    UniValue CallRPC(const std::string& rpc_method, const std::vector<std::string>& arguments)
    {
        JSONRPCRequest request;
        request.context = &m_node;
        request.strMethod = rpc_method;
        request.params = RPCConvertValues(rpc_method, arguments);
        return tableRPC.execute(request);
    }

    std::vector<std::string> GetRPCCommands() const
    {
        return tableRPC.listCommands();
    }
};

RPCFuzzTestingSetup* rpc_testing_setup = nullptr;
std::string g_limit_to_rpc_command;

// RPC commands which are not appropriate for fuzzing: such as RPC commands
// reading or writing to a filename passed as an RPC parameter, RPC commands
// resulting in network activity, etc.
const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
    "addconnection",  // avoid DNS lookups
    "addnode",        // avoid DNS lookups
    "addpeeraddress", // avoid DNS lookups
    "analyzepsbt",    // avoid signed integer overflow in CFeeRate::GetFee(unsigned long) (https://github.com/bitcoin/bitcoin/issues/20607)
    "dumptxoutset",   // avoid writing to disk
#ifdef ENABLE_WALLET
    "dumpwallet", // avoid writing to disk
#endif
    "echoipc",           // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
    "generatetoaddress", // avoid timeout
    "gettxoutproof",     // avoid slow execution
#ifdef ENABLE_WALLET
    "importwallet", // avoid reading from disk
    "loadwallet",   // avoid reading from disk
#endif
    "mockscheduler",         // avoid assertion failure (Assertion `delta_seconds.count() > 0 && delta_seconds < std::chrono::hours{1}' failed.)
    "prioritisetransaction", // avoid signed integer overflow in CTxMemPool::PrioritiseTransaction(uint256 const&, long const&) (https://github.com/bitcoin/bitcoin/issues/20626)
    "setban",                // avoid DNS lookups
    "stop",                  // avoid shutdown state
};

// RPC commands which are safe for fuzzing.
const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
    "clearbanned",
    "combinepsbt",
    "combinerawtransaction",
    "converttopsbt",
    "createmultisig",
    "createpsbt",
    "createrawtransaction",
    "decodepsbt",
    "decoderawtransaction",
    "decodescript",
    "deriveaddresses",
    "disconnectnode",
    "echo",
    "echojson",
    "estimaterawfee",
    "estimatesmartfee",
    "finalizepsbt",
    "generate",
    "generateblock",
    "generatetodescriptor",
    "getaddednodeinfo",
    "getbestblockhash",
    "getblock",
    "getblockchaininfo",
    "getblockcount",
    "getblockfilter",
    "getblockhash",
    "getblockheader",
    "getblockstats",
    "getblocktemplate",
    "getchaintips",
    "getchaintxstats",
    "getconnectioncount",
    "getdescriptorinfo",
    "getdifficulty",
    "getindexinfo",
    "getmemoryinfo",
    "getmempoolancestors",
    "getmempooldescendants",
    "getmempoolentry",
    "getmempoolinfo",
    "getmininginfo",
    "getnettotals",
    "getnetworkhashps",
    "getnetworkinfo",
    "getnodeaddresses",
    "getpeerinfo",
    "getrawmempool",
    "getrawtransaction",
    "getrpcinfo",
    "gettxout",
    "gettxoutsetinfo",
    "help",
    "invalidateblock",
    "joinpsbts",
    "listbanned",
    "logging",
    "ping",
    "preciousblock",
    "pruneblockchain",
    "reconsiderblock",
    "savemempool",
    "scantxoutset",
    "sendrawtransaction",
    "setmocktime",
    "setnetworkactive",
    "signmessagewithprivkey",
    "signrawtransactionwithkey",
    "submitblock",
    "submitheader",
    "syncwithvalidationinterfacequeue",
    "testmempoolaccept",
    "uptime",
    "utxoupdatepsbt",
    "validateaddress",
    "verifychain",
    "verifymessage",
    "verifytxoutproof",
    "waitforblock",
    "waitforblockheight",
    "waitfornewblock",
};

std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
{
    const size_t max_string_length = 4096;
    std::string r;
    CallOneOf(
        fuzzed_data_provider,
        [&] {
            // string argument
            r = fuzzed_data_provider.ConsumeRandomLengthString(max_string_length);
        },
        [&] {
            // base64 argument
            r = EncodeBase64(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
        },
        [&] {
            // hex argument
            r = HexStr(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
        },
        [&] {
            // bool argument
            r = fuzzed_data_provider.ConsumeBool() ? "true" : "false";
        },
        [&] {
            // range argument
            r = "[" + ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>()) + "," + ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>()) + "]";
        },
        [&] {
            // integral argument (int64_t)
            r = ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>());
        },
        [&] {
            // integral argument (uint64_t)
            r = ToString(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
        },
        [&] {
            // floating point argument
            r = strprintf("%f", fuzzed_data_provider.ConsumeFloatingPoint<double>());
        },
        [&] {
            // tx destination argument
            r = EncodeDestination(ConsumeTxDestination(fuzzed_data_provider));
        },
        [&] {
            // uint160 argument
            r = ConsumeUInt160(fuzzed_data_provider).ToString();
        },
        [&] {
            // uint256 argument
            r = ConsumeUInt256(fuzzed_data_provider).ToString();
        },
        [&] {
            // base32 argument
            r = EncodeBase32(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
        },
        [&] {
            // base58 argument
            r = EncodeBase58(MakeUCharSpan(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length)));
        },
        [&] {
            // base58 argument with checksum
            r = EncodeBase58Check(MakeUCharSpan(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length)));
        },
        [&] {
            // hex encoded block
            std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
            if (!opt_block) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
            data_stream << *opt_block;
            r = HexStr(data_stream);
        },
        [&] {
            // hex encoded block header
            std::optional<CBlockHeader> opt_block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
            if (!opt_block_header) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
            data_stream << *opt_block_header;
            r = HexStr(data_stream);
        },
        [&] {
            // hex encoded tx
            std::optional<CMutableTransaction> opt_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
            if (!opt_tx) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, fuzzed_data_provider.ConsumeBool() ? PROTOCOL_VERSION : (PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)};
            data_stream << *opt_tx;
            r = HexStr(data_stream);
        },
        [&] {
            // base64 encoded psbt
            std::optional<PartiallySignedTransaction> opt_psbt = ConsumeDeserializable<PartiallySignedTransaction>(fuzzed_data_provider);
            if (!opt_psbt) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
            data_stream << *opt_psbt;
            r = EncodeBase64({data_stream.begin(), data_stream.end()});
        },
        [&] {
            // base58 encoded key
            const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(32);
            CKey key;
            key.Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.ConsumeBool());
            if (!key.IsValid()) {
                return;
            }
            r = EncodeSecret(key);
        },
        [&] {
            // hex encoded pubkey
            const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(32);
            CKey key;
            key.Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.ConsumeBool());
            if (!key.IsValid()) {
                return;
            }
            r = HexStr(key.GetPubKey());
        });
    return r;
}

std::string ConsumeArrayRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
{
    std::vector<std::string> scalar_arguments;
    while (fuzzed_data_provider.ConsumeBool()) {
        scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider));
    }
    return "[\"" + Join(scalar_arguments, "\",\"") + "\"]";
}

std::string ConsumeRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
{
    return fuzzed_data_provider.ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
}

RPCFuzzTestingSetup* InitializeRPCFuzzTestingSetup()
{
    static const auto setup = MakeNoLogFileContext<RPCFuzzTestingSetup>();
    SetRPCWarmupFinished();
    return setup.get();
}
}; // namespace

void initialize_rpc()
{
    rpc_testing_setup = InitializeRPCFuzzTestingSetup();
    const std::vector<std::string> supported_rpc_commands = rpc_testing_setup->GetRPCCommands();
    for (const std::string& rpc_command : supported_rpc_commands) {
        const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
        const bool not_safe_for_fuzzing = std::find(RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end();
        if (!(safe_for_fuzzing || not_safe_for_fuzzing)) {
            std::cerr << "Error: RPC command \"" << rpc_command << "\" not found in RPC_COMMANDS_SAFE_FOR_FUZZING or RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
        if (safe_for_fuzzing && not_safe_for_fuzzing) {
            std::cerr << "Error: RPC command \"" << rpc_command << "\" found in *both* RPC_COMMANDS_SAFE_FOR_FUZZING and RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
    }
    for (const std::string& rpc_command : RPC_COMMANDS_SAFE_FOR_FUZZING) {
        const bool supported_rpc_command = std::find(supported_rpc_commands.begin(), supported_rpc_commands.end(), rpc_command) != supported_rpc_commands.end();
        if (!supported_rpc_command) {
            std::cerr << "Error: Unknown RPC command \"" << rpc_command << "\" found in RPC_COMMANDS_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
    }
    for (const std::string& rpc_command : RPC_COMMANDS_NOT_SAFE_FOR_FUZZING) {
        const bool supported_rpc_command = std::find(supported_rpc_commands.begin(), supported_rpc_commands.end(), rpc_command) != supported_rpc_commands.end();
        if (!supported_rpc_command) {
            std::cerr << "Error: Unknown RPC command \"" << rpc_command << "\" found in RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
    }
    const char* limit_to_rpc_command_env = std::getenv("LIMIT_TO_RPC_COMMAND");
    if (limit_to_rpc_command_env != nullptr) {
        g_limit_to_rpc_command = std::string{limit_to_rpc_command_env};
    }
}

FUZZ_TARGET_INIT(rpc, initialize_rpc)
{
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    SetMockTime(ConsumeTime(fuzzed_data_provider));
    const std::string rpc_command = fuzzed_data_provider.ConsumeRandomLengthString(64);
    if (!g_limit_to_rpc_command.empty() && rpc_command != g_limit_to_rpc_command) {
        return;
    }
    const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
    if (!safe_for_fuzzing) {
        return;
    }
    std::vector<std::string> arguments;
    while (fuzzed_data_provider.ConsumeBool()) {
        arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider));
    }
    try {
        rpc_testing_setup->CallRPC(rpc_command, arguments);
    } catch (const UniValue&) {
    } catch (const std::runtime_error&) {
    }
}
<commit_msg>fuzz: RPC fuzzer post-merge follow-ups. Remove unused includes. Update list of fuzzed RPC commands.<commit_after>// Copyright (c) 2021 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 <base58.h>
#include <core_io.h>
#include <key.h>
#include <key_io.h>
#include <node/context.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <psbt.h>
#include <rpc/blockchain.h>
#include <rpc/client.h>
#include <rpc/request.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <span.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <tinyformat.h>
#include <univalue.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/time.h>

#include <cstdint>
#include <iostream>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>

namespace {
struct RPCFuzzTestingSetup : public TestingSetup {
    RPCFuzzTestingSetup(const std::string& chain_name, const std::vector<const char*>& extra_args) : TestingSetup{chain_name, extra_args}
    {
    }

    UniValue CallRPC(const std::string& rpc_method, const std::vector<std::string>& arguments)
    {
        JSONRPCRequest request;
        request.context = &m_node;
        request.strMethod = rpc_method;
        request.params = RPCConvertValues(rpc_method, arguments);
        return tableRPC.execute(request);
    }

    std::vector<std::string> GetRPCCommands() const
    {
        return tableRPC.listCommands();
    }
};

RPCFuzzTestingSetup* rpc_testing_setup = nullptr;
std::string g_limit_to_rpc_command;

// RPC commands which are not appropriate for fuzzing: such as RPC commands
// reading or writing to a filename passed as an RPC parameter, RPC commands
// resulting in network activity, etc.
const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
    "addconnection",  // avoid DNS lookups
    "addnode",        // avoid DNS lookups
    "addpeeraddress", // avoid DNS lookups
    "analyzepsbt",    // avoid signed integer overflow in CFeeRate::GetFee(unsigned long) (https://github.com/bitcoin/bitcoin/issues/20607)
    "dumptxoutset",   // avoid writing to disk
#ifdef ENABLE_WALLET
    "dumpwallet", // avoid writing to disk
#endif
    "echoipc",              // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
    "generatetoaddress",    // avoid prohibitively slow execution (when `num_blocks` is large)
    "generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
    "gettxoutproof",        // avoid prohibitively slow execution
#ifdef ENABLE_WALLET
    "importwallet", // avoid reading from disk
    "loadwallet",   // avoid reading from disk
#endif
    "prioritisetransaction", // avoid signed integer overflow in CTxMemPool::PrioritiseTransaction(uint256 const&, long const&) (https://github.com/bitcoin/bitcoin/issues/20626)
    "savemempool",           // disabled as a precautionary measure: may take a file path argument in the future
    "setban",                // avoid DNS lookups
    "stop",                  // avoid shutdown state
};

// RPC commands which are safe for fuzzing.
const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
    "clearbanned",
    "combinepsbt",
    "combinerawtransaction",
    "converttopsbt",
    "createmultisig",
    "createpsbt",
    "createrawtransaction",
    "decodepsbt",
    "decoderawtransaction",
    "decodescript",
    "deriveaddresses",
    "disconnectnode",
    "echo",
    "echojson",
    "estimaterawfee",
    "estimatesmartfee",
    "finalizepsbt",
    "generate",
    "generateblock",
    "getaddednodeinfo",
    "getbestblockhash",
    "getblock",
    "getblockchaininfo",
    "getblockcount",
    "getblockfilter",
    "getblockhash",
    "getblockheader",
    "getblockstats",
    "getblocktemplate",
    "getchaintips",
    "getchaintxstats",
    "getconnectioncount",
    "getdescriptorinfo",
    "getdifficulty",
    "getindexinfo",
    "getmemoryinfo",
    "getmempoolancestors",
    "getmempooldescendants",
    "getmempoolentry",
    "getmempoolinfo",
    "getmininginfo",
    "getnettotals",
    "getnetworkhashps",
    "getnetworkinfo",
    "getnodeaddresses",
    "getpeerinfo",
    "getrawmempool",
    "getrawtransaction",
    "getrpcinfo",
    "gettxout",
    "gettxoutsetinfo",
    "help",
    "invalidateblock",
    "joinpsbts",
    "listbanned",
    "logging",
    "mockscheduler",
    "ping",
    "preciousblock",
    "pruneblockchain",
    "reconsiderblock",
    "scantxoutset",
    "sendrawtransaction",
    "setmocktime",
    "setnetworkactive",
    "signmessagewithprivkey",
    "signrawtransactionwithkey",
    "submitblock",
    "submitheader",
    "syncwithvalidationinterfacequeue",
    "testmempoolaccept",
    "uptime",
    "utxoupdatepsbt",
    "validateaddress",
    "verifychain",
    "verifymessage",
    "verifytxoutproof",
    "waitforblock",
    "waitforblockheight",
    "waitfornewblock",
};

std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
{
    const size_t max_string_length = 4096;
    std::string r;
    CallOneOf(
        fuzzed_data_provider,
        [&] {
            // string argument
            r = fuzzed_data_provider.ConsumeRandomLengthString(max_string_length);
        },
        [&] {
            // base64 argument
            r = EncodeBase64(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
        },
        [&] {
            // hex argument
            r = HexStr(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
        },
        [&] {
            // bool argument
            r = fuzzed_data_provider.ConsumeBool() ? "true" : "false";
        },
        [&] {
            // range argument
            r = "[" + ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>()) + "," + ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>()) + "]";
        },
        [&] {
            // integral argument (int64_t)
            r = ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>());
        },
        [&] {
            // integral argument (uint64_t)
            r = ToString(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
        },
        [&] {
            // floating point argument
            r = strprintf("%f", fuzzed_data_provider.ConsumeFloatingPoint<double>());
        },
        [&] {
            // tx destination argument
            r = EncodeDestination(ConsumeTxDestination(fuzzed_data_provider));
        },
        [&] {
            // uint160 argument
            r = ConsumeUInt160(fuzzed_data_provider).ToString();
        },
        [&] {
            // uint256 argument
            r = ConsumeUInt256(fuzzed_data_provider).ToString();
        },
        [&] {
            // base32 argument
            r = EncodeBase32(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
        },
        [&] {
            // base58 argument
            r = EncodeBase58(MakeUCharSpan(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length)));
        },
        [&] {
            // base58 argument with checksum
            r = EncodeBase58Check(MakeUCharSpan(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length)));
        },
        [&] {
            // hex encoded block
            std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
            if (!opt_block) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
            data_stream << *opt_block;
            r = HexStr(data_stream);
        },
        [&] {
            // hex encoded block header
            std::optional<CBlockHeader> opt_block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
            if (!opt_block_header) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
            data_stream << *opt_block_header;
            r = HexStr(data_stream);
        },
        [&] {
            // hex encoded tx
            std::optional<CMutableTransaction> opt_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
            if (!opt_tx) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, fuzzed_data_provider.ConsumeBool() ? PROTOCOL_VERSION : (PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)};
            data_stream << *opt_tx;
            r = HexStr(data_stream);
        },
        [&] {
            // base64 encoded psbt
            std::optional<PartiallySignedTransaction> opt_psbt = ConsumeDeserializable<PartiallySignedTransaction>(fuzzed_data_provider);
            if (!opt_psbt) {
                return;
            }
            CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
            data_stream << *opt_psbt;
            r = EncodeBase64({data_stream.begin(), data_stream.end()});
        },
        [&] {
            // base58 encoded key
            const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(32);
            CKey key;
            key.Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.ConsumeBool());
            if (!key.IsValid()) {
                return;
            }
            r = EncodeSecret(key);
        },
        [&] {
            // hex encoded pubkey
            const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(32);
            CKey key;
            key.Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.ConsumeBool());
            if (!key.IsValid()) {
                return;
            }
            r = HexStr(key.GetPubKey());
        });
    return r;
}

std::string ConsumeArrayRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
{
    std::vector<std::string> scalar_arguments;
    while (fuzzed_data_provider.ConsumeBool()) {
        scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider));
    }
    return "[\"" + Join(scalar_arguments, "\",\"") + "\"]";
}

std::string ConsumeRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
{
    return fuzzed_data_provider.ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
}

RPCFuzzTestingSetup* InitializeRPCFuzzTestingSetup()
{
    static const auto setup = MakeNoLogFileContext<RPCFuzzTestingSetup>();
    SetRPCWarmupFinished();
    return setup.get();
}
}; // namespace

void initialize_rpc()
{
    rpc_testing_setup = InitializeRPCFuzzTestingSetup();
    const std::vector<std::string> supported_rpc_commands = rpc_testing_setup->GetRPCCommands();
    for (const std::string& rpc_command : supported_rpc_commands) {
        const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
        const bool not_safe_for_fuzzing = std::find(RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end();
        if (!(safe_for_fuzzing || not_safe_for_fuzzing)) {
            std::cerr << "Error: RPC command \"" << rpc_command << "\" not found in RPC_COMMANDS_SAFE_FOR_FUZZING or RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
        if (safe_for_fuzzing && not_safe_for_fuzzing) {
            std::cerr << "Error: RPC command \"" << rpc_command << "\" found in *both* RPC_COMMANDS_SAFE_FOR_FUZZING and RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
    }
    for (const std::string& rpc_command : RPC_COMMANDS_SAFE_FOR_FUZZING) {
        const bool supported_rpc_command = std::find(supported_rpc_commands.begin(), supported_rpc_commands.end(), rpc_command) != supported_rpc_commands.end();
        if (!supported_rpc_command) {
            std::cerr << "Error: Unknown RPC command \"" << rpc_command << "\" found in RPC_COMMANDS_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
    }
    for (const std::string& rpc_command : RPC_COMMANDS_NOT_SAFE_FOR_FUZZING) {
        const bool supported_rpc_command = std::find(supported_rpc_commands.begin(), supported_rpc_commands.end(), rpc_command) != supported_rpc_commands.end();
        if (!supported_rpc_command) {
            std::cerr << "Error: Unknown RPC command \"" << rpc_command << "\" found in RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
            std::terminate();
        }
    }
    const char* limit_to_rpc_command_env = std::getenv("LIMIT_TO_RPC_COMMAND");
    if (limit_to_rpc_command_env != nullptr) {
        g_limit_to_rpc_command = std::string{limit_to_rpc_command_env};
    }
}

FUZZ_TARGET_INIT(rpc, initialize_rpc)
{
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    SetMockTime(ConsumeTime(fuzzed_data_provider));
    const std::string rpc_command = fuzzed_data_provider.ConsumeRandomLengthString(64);
    if (!g_limit_to_rpc_command.empty() && rpc_command != g_limit_to_rpc_command) {
        return;
    }
    const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
    if (!safe_for_fuzzing) {
        return;
    }
    std::vector<std::string> arguments;
    while (fuzzed_data_provider.ConsumeBool()) {
        arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider));
    }
    try {
        rpc_testing_setup->CallRPC(rpc_command, arguments);
    } catch (const UniValue&) {
    } catch (const std::runtime_error&) {
    }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

#include <prussdrv.h>
#include <pruss_intc_mapping.h>

#define PRU_BIN_NAME  "./pru0.bin"

#define MS_TO_CYCLE(ms)    ((ms)*2000000/1000)

#define DDR_BASEADDR     0x80000000
#define OFFSET_DDR       0x00001000
#define OFFSET_SHAREDRAM 2048       //equivalent with 0x00002000

#define PRUSS0_SHARED_DATARAM    4

typedef unsigned int uint32_t;

struct prupwm_param{
    uint32_t flag;
    uint32_t period;
    uint32_t duty[6];
};

void dump_data_duty(struct prupwm_param *pwm_param)
{
    int i;

    printf("Duty FOR PRM PWM:\n");
    printf("==============================================\n");
    for(i=0;i<6;i++) {
        printf("%x08\n", pwm_param->duty[i]);
    }
    printf("==============================================\n");
}

void dump_data_flag(struct prupwm_param *pwm_param)
{
    int i;

    printf("switch FOR PRM PWM:\n");
    printf("==============================================\n");
    for(i=0;i<6;i++) {
        printf("PWM-%d: ", i);
        if(pwm_param->flag & (1 << i))
            printf("ON\n");
        else
            printf("OFF\n");
    }
    printf("==============================================\n");
}

void switch_flag(struct prupwm_param *pwm_param, int bit)
{
    if(pwm_param->flag & (1<<bit)) {
        pwm_param->flag &= (~(1<<bit));
    } else {
        pwm_param->flag |= (1<<bit);
    }
}

int
main(int argc, char const *argv[])
{
    int ret;
    int i;
    void *sharedMem;
    struct prupwm_param *pwm_param;

    tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

    printf("\nINFO: Starting PRU.\r\n");
    /* Initialize the PRU */
    prussdrv_init ();

    /* Open PRU Interrupt */
    ret = prussdrv_open(PRU_EVTOUT_0);
    if (ret)
    {
        printf("prussdrv_open open failed\n");
        return -1;
    }

     /* Get the interrupt initialized */
    prussdrv_pruintc_init(&pruss_intc_initdata);

    prussdrv_map_prumem(PRUSS0_SHARED_DATARAM, &sharedMem);

    pwm_param = (struct prupwm_param *)(sharedMem + OFFSET_DDR);
    memset(pwm_param, 0, sizeof(struct prupwm_param));
    pwm_param->flag = 0xcf;
    pwm_param->period = MS_TO_CYCLE(20);

    for(i=0;i<6;i++) {
        pwm_param->duty[i] = MS_TO_CYCLE(1.5);
    }

    /* Execute example on PRU */
    ret = prussdrv_exec_program (0, PRU_BIN_NAME);
    printf("\tINFO: Executing PRU. ret=%d\r\n", ret);

    while(1) {
        switch(getchar())
        {
            case 'd':
                if(pwm_param->duty[0] > 100)
                    pwm_param->duty[0] -= 100;
                else
                    pwm_param->duty[0] = 0;

                dump_data_duty(pwm_param);
                break;

            case 'u':
                if(pwm_param->duty[0] < pwm_param->period)
                    pwm_param->duty[0] += 100;
                else
                    pwm_param->duty[0] = pwm_param->period;

                dump_data_duty(pwm_param);
                break;

            case 'q':
                return -1;

            case '0':
                switch_flag(pwm_param, 0);
                dump_data_flag(pwm_param);
                break;
            case '1':
                switch_flag(pwm_param, 1);
                dump_data_flag(pwm_param);
                break;
            case '2':
                switch_flag(pwm_param, 2);
                dump_data_flag(pwm_param);
                break;
            case '3':
                switch_flag(pwm_param, 3);
                dump_data_flag(pwm_param);
                break;
            case '4':
                switch_flag(pwm_param, 4);
                dump_data_flag(pwm_param);
                break;
            case '5':
                switch_flag(pwm_param, 5);
                dump_data_flag(pwm_param);
                break;

            default:
                dump_data_flag(pwm_param);
                dump_data_duty(pwm_param);
                break;
        }
        usleep(100);
    }
    prussdrv_pru_disable(0);
    prussdrv_exit ();

    return 0;
}
<commit_msg>update test for pru pwm<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

#include <prussdrv.h>
#include <pruss_intc_mapping.h>

#define PRU_BIN_NAME  "./pru0.bin"

#define MS_TO_CYCLE(ms)    ((ms)*2000000/1000)

#define DDR_BASEADDR     0x80000000
#define OFFSET_DDR       0x00001000
#define OFFSET_SHAREDRAM 2048       //equivalent with 0x00002000

#define PRUSS0_SHARED_DATARAM    4

typedef unsigned int uint32_t;

struct prupwm_param{
    uint32_t flag;
    uint32_t period;
    uint32_t duty[6];
};

void dump_data_duty(struct prupwm_param *pwm_param)
{
    int i;

    printf("Duty FOR PRM PWM:\n");
    printf("==============================================\n");
    for(i=0;i<6;i++) {
        printf("%x08\n", pwm_param->duty[i]);
    }
    printf("==============================================\n");
}

void dump_data_flag(struct prupwm_param *pwm_param)
{
    int i;

    printf("switch FOR PRM PWM:\n");
    printf("==============================================\n");
    for(i=0;i<6;i++) {
        printf("PWM-%d: ", i);
        if(pwm_param->flag & (1 << i))
            printf("ON\n");
        else
            printf("OFF\n");
    }
    printf("==============================================\n");
}

void switch_flag(struct prupwm_param *pwm_param, int bit)
{
    if(pwm_param->flag & (1<<bit)) {
        pwm_param->flag &= (~(1<<bit));
    } else {
        pwm_param->flag |= (1<<bit);
    }
}

int
main(int argc, char const *argv[])
{
    int ret;
    int i;
    void *sharedMem;
    struct prupwm_param *pwm_param;

    tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

    printf("\nINFO: Starting PRU.\r\n");
    /* Initialize the PRU */
    prussdrv_init ();

    /* Open PRU Interrupt */
    ret = prussdrv_open(PRU_EVTOUT_0);
    if (ret)
    {
        printf("prussdrv_open open failed\n");
        return -1;
    }

     /* Get the interrupt initialized */
    prussdrv_pruintc_init(&pruss_intc_initdata);

    prussdrv_map_prumem(PRUSS0_SHARED_DATARAM, &sharedMem);

    pwm_param = (struct prupwm_param *)(sharedMem + OFFSET_SHAREDRAM);
    memset(pwm_param, 0, sizeof(struct prupwm_param));
    pwm_param->flag = 0xcf;
    pwm_param->period = MS_TO_CYCLE(20);

    for(i=0;i<6;i++) {
        pwm_param->duty[i] = MS_TO_CYCLE(1.5);
    }

    /* Execute example on PRU */
    ret = prussdrv_exec_program (0, PRU_BIN_NAME);
    printf("\tINFO: Executing PRU. ret=%d\r\n", ret);

    while(1) {
        switch(getchar())
        {
            case 'd':
                if(pwm_param->duty[0] > 100)
                    pwm_param->duty[0] -= 100;
                else
                    pwm_param->duty[0] = 0;

                dump_data_duty(pwm_param);
                break;

            case 'u':
                if(pwm_param->duty[0] < pwm_param->period)
                    pwm_param->duty[0] += 100;
                else
                    pwm_param->duty[0] = pwm_param->period;

                dump_data_duty(pwm_param);
                break;

            case 'q':
                return -1;

            case '0':
                switch_flag(pwm_param, 0);
                dump_data_flag(pwm_param);
                break;
            case '1':
                switch_flag(pwm_param, 1);
                dump_data_flag(pwm_param);
                break;
            case '2':
                switch_flag(pwm_param, 2);
                dump_data_flag(pwm_param);
                break;
            case '3':
                switch_flag(pwm_param, 3);
                dump_data_flag(pwm_param);
                break;
            case '4':
                switch_flag(pwm_param, 4);
                dump_data_flag(pwm_param);
                break;
            case '5':
                switch_flag(pwm_param, 5);
                dump_data_flag(pwm_param);
                break;

            default:
                dump_data_flag(pwm_param);
                dump_data_duty(pwm_param);
                break;
        }
        usleep(100);
    }
    prussdrv_pru_disable(0);
    prussdrv_exit ();

    return 0;
}
<|endoftext|>