Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Valgrind detected an invalid read #254

Closed
nqf opened this issue May 19, 2022 · 3 comments · Fixed by #256
Closed

Valgrind detected an invalid read #254

nqf opened this issue May 19, 2022 · 3 comments · Fixed by #256

Comments

@nqf
Copy link

nqf commented May 19, 2022

hi, I am currently trying to use this library, But Valgrind detected an invalid read, This makes me very confused,
could you give me some advice?

# This schema is what https://graphql.org/learn/ uses.
# It is extracted from https://github.com/graphql/graphql-js/blob/main/src/__tests__/starWarsSchema.ts.

enum Episode { NEW_HOPE, EMPIRE, JEDI }

interface Character {
  id: ID!
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

type Human implements Character {
  id: ID!
  name: String
  friends: [Character]
  appearsIn: [Episode]
  homePlanet: String
}

type Query {
  human(id: ID!): Human
}
#pragma once

#include <atomic>
#include <memory>
#include <stack>

#include "CharacterObject.h"
#include "FantasySchema.h"
#include "HumanObject.h"
#include "QueryObject.h"

namespace graphql::fantasy {

class MyHuman {
public:
	MyHuman(std::string&& id, std::optional<std::string>&& name, std::vector<Episode>&& appearsIn,
		std::optional<std::string>&& homePlanet) noexcept
		: id_{std::move(id)}
		, name_{std::move(name)}
		, appearsIn_{std::move(appearsIn)}
		, homePlanet_{std::move(homePlanet)} {
	}

	void addFriends(std::string friends) noexcept {
		std::cout << "MyHuman::addFriends" << std::endl;
	}

	const response::IdType& getId() const noexcept {
		std::cout << "MyHuman::getId" << std::endl;
		return id_;
	}

	const std::optional<std::string>& getName() const noexcept {
		std::cout << "MyHuman::getName" << std::endl;
		return name_;
	}

	std::optional<std::vector<std::shared_ptr<object::Character>>> getFriends() const noexcept {
		std::cout << "MyHuman::getFriends" << std::endl;
		return std::nullopt;
	}

	std::optional<std::vector<std::optional<Episode>>> getAppearsIn() const noexcept {
		std::cout << "MyHuman::getAppearsIn" << std::endl;
		std::vector<std::optional<Episode>> result(appearsIn_.size());

		std::transform(appearsIn_.begin(),
			appearsIn_.end(),
			result.begin(),
			[](const auto& entry) noexcept {
				return std::make_optional(entry);
			});

		return result.empty() ? std::nullopt : std::make_optional(std::move(result));
	}

	const std::optional<std::string>& getHomePlanet() const noexcept {
		std::cout << "MyHuman::getHomePlanet" << std::endl;
		return homePlanet_;
	}

private:
	const response::IdType id_;
	const std::optional<std::string> name_;
	const std::vector<Episode> appearsIn_;
	const std::optional<std::string> homePlanet_;
};

struct MockService {
	std::shared_ptr<Operations> service{};
};

struct RequestState : service::RequestState {
	RequestState(uint32_t id)
		: request_id(id) {
	}

	uint32_t request_id;
};

class Query : public std::enable_shared_from_this<Query> {
public:
	service::AwaitableObject<std::shared_ptr<graphql::fantasy::object::Human>> getHuman(response::IdType id) {
		std::cout << "1" << std::endl;
		//std::cout << std::static_pointer_cast<RequestState>(params.state)->request_id << std::endl;
		// auto ptr = std::make_shared<MyHuman>("1000", "lilei", std::vector<Episode>{Episode::NEW_HOPE}, "china");
		// co_return std::make_shared<graphql::fantasy::object::Human>(ptr);
		co_return nullptr;
	}
	service::AwaitableObject<std::shared_ptr<graphql::fantasy::object::Human>> getHuman(graphql::service::FieldParams params, response::IdType id) {
		std::cout << "2" << std::endl;
		co_return nullptr;
	}
};

std::unique_ptr<MockService> mock_service() noexcept {
	auto result = std::make_unique<MockService>();
	auto query = std::make_shared<Query>();
	result->service = std::make_shared<Operations>(query);
	return result;
}

} // namespace graphql::fantasy
#include <iostream>

#include "graphqlservice/JSONResponse.h"
#include "mock.h"

using namespace std::literals;

int main() {
	const auto mock_service = graphql::fantasy::mock_service();
	const auto& service = mock_service->service;
	std::string cmd{R"({human(id: "1000") {name}})"};
	std::cout << "[" << cmd << "]" << std::endl;
	try {
		graphql::peg::ast ast = graphql::peg::parseString(cmd);
		if (!ast.root) {
			std::cerr << "Unknown error!" << std::endl;
			std::cerr << std::endl;
			return 1;
		}
		graphql::response::Value variables(graphql::response::Type::Map);
		auto state = std::make_shared<graphql::fantasy::RequestState>(1000);
		const auto worker = std::make_shared<std::suspend_never>();
		graphql::service::RequestResolveParams pp{
			ast,
			""sv,
			std::move(variables),
			graphql::service::await_async{worker},
			state,
		};
		auto result = service->resolve(pp);
		std::cout << graphql::response::toJSON(result.get()) << std::endl;
	} catch (const std::runtime_error& ex) {
		std::cerr << ex.what() << std::endl;
		return 1;
	}
	return 0;
}
==25784== Memcheck, a memory error detector
==25784== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25784== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==25784== Command: ./main
==25784== Parent PID: 1637
==25784== 
==25784== Invalid read of size 2
==25784==    at 0x4C320E0: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
==25784==    by 0x421F9C: std::char_traits<char>::copy(char*, char const*, unsigned long) (char_traits.h:409)
==25784==    by 0x42952F: std::string::_M_copy(char*, char const*, unsigned long) (basic_string.h:3463)
==25784==    by 0x436680: std::string::_S_copy_chars(char*, char const*, char const*) (basic_string.h:3510)
==25784==    by 0x430038: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:612)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x44B3DD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string::__sv_wrapper, std::allocator<char> const&) (basic_string.h:3569)
==25784==    by 0x44AC7D: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) (basic_string.h:3759)
==25784==    by 0x4A58B4: tao::graphqlpeg::position::position<std::basic_string_view<char, std::char_traits<char> > const&>(tao::graphqlpeg::internal::iterator const&, std::basic_string_view<char, std::char_traits<char> > const&) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x49E710: tao::graphqlpeg::parse_tree::basic_node<graphql::peg::ast_node, std::basic_string_view<char, std::char_traits<char> > >::begin() const (in /home/fantasy/next/graphql-server/build/main)
==25784==  Address 0x6070bb8 is 24 bytes inside a block of size 32 free'd
==25784==    at 0x4C2DD8B: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==25784==    by 0x4365D0: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:145)
==25784==    by 0x429416: deallocate (allocator.h:211)
==25784==    by 0x429416: std::string::_Rep::_M_destroy(std::allocator<char> const&) (basic_string.tcc:880)
==25784==    by 0x425A9C: std::string::_Rep::_M_dispose(std::allocator<char> const&) (basic_string.h:3351)
==25784==    by 0x423DC1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (basic_string.h:3766)
==25784==    by 0x5C72E1: tao::graphqlpeg::internal::memory_input_base<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input_base() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C72FD: tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C7875: graphql::peg::depth_limit_input<tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string> >::~depth_limit_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A74DB: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784==  Block was alloc'd at
==25784==    at 0x4C2B788: operator new(unsigned long) (vg_replace_malloc.c:417)
==25784==    by 0x4365A6: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:127)
==25784==    by 0x4292CA: allocate (allocator.h:197)
==25784==    by 0x4292CA: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:1048)
==25784==    by 0x430012: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:610)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x5C607F: std::literals::string_literals::operator"" s(char const*, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A7433: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784== 
==25784== Invalid read of size 2
==25784==    at 0x4C320EF: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
==25784==    by 0x421F9C: std::char_traits<char>::copy(char*, char const*, unsigned long) (char_traits.h:409)
==25784==    by 0x42952F: std::string::_M_copy(char*, char const*, unsigned long) (basic_string.h:3463)
==25784==    by 0x436680: std::string::_S_copy_chars(char*, char const*, char const*) (basic_string.h:3510)
==25784==    by 0x430038: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:612)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x44B3DD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string::__sv_wrapper, std::allocator<char> const&) (basic_string.h:3569)
==25784==    by 0x44AC7D: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) (basic_string.h:3759)
==25784==    by 0x4A58B4: tao::graphqlpeg::position::position<std::basic_string_view<char, std::char_traits<char> > const&>(tao::graphqlpeg::internal::iterator const&, std::basic_string_view<char, std::char_traits<char> > const&) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x49E710: tao::graphqlpeg::parse_tree::basic_node<graphql::peg::ast_node, std::basic_string_view<char, std::char_traits<char> > >::begin() const (in /home/fantasy/next/graphql-server/build/main)
==25784==  Address 0x6070bbc is 28 bytes inside a block of size 32 free'd
==25784==    at 0x4C2DD8B: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==25784==    by 0x4365D0: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:145)
==25784==    by 0x429416: deallocate (allocator.h:211)
==25784==    by 0x429416: std::string::_Rep::_M_destroy(std::allocator<char> const&) (basic_string.tcc:880)
==25784==    by 0x425A9C: std::string::_Rep::_M_dispose(std::allocator<char> const&) (basic_string.h:3351)
==25784==    by 0x423DC1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (basic_string.h:3766)
==25784==    by 0x5C72E1: tao::graphqlpeg::internal::memory_input_base<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input_base() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C72FD: tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C7875: graphql::peg::depth_limit_input<tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string> >::~depth_limit_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A74DB: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784==  Block was alloc'd at
==25784==    at 0x4C2B788: operator new(unsigned long) (vg_replace_malloc.c:417)
==25784==    by 0x4365A6: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:127)
==25784==    by 0x4292CA: allocate (allocator.h:197)
==25784==    by 0x4292CA: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:1048)
==25784==    by 0x430012: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:610)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x5C607F: std::literals::string_literals::operator"" s(char const*, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A7433: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784== 
==25784== Invalid read of size 1
==25784==    at 0x4C322E0: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
==25784==    by 0x421F9C: std::char_traits<char>::copy(char*, char const*, unsigned long) (char_traits.h:409)
==25784==    by 0x42952F: std::string::_M_copy(char*, char const*, unsigned long) (basic_string.h:3463)
==25784==    by 0x436680: std::string::_S_copy_chars(char*, char const*, char const*) (basic_string.h:3510)
==25784==    by 0x430038: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:612)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x44B3DD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string::__sv_wrapper, std::allocator<char> const&) (basic_string.h:3569)
==25784==    by 0x44AC7D: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) (basic_string.h:3759)
==25784==    by 0x4A58B4: tao::graphqlpeg::position::position<std::basic_string_view<char, std::char_traits<char> > const&>(tao::graphqlpeg::internal::iterator const&, std::basic_string_view<char, std::char_traits<char> > const&) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x49E710: tao::graphqlpeg::parse_tree::basic_node<graphql::peg::ast_node, std::basic_string_view<char, std::char_traits<char> > >::begin() const (in /home/fantasy/next/graphql-server/build/main)
==25784==  Address 0x6070bbe is 30 bytes inside a block of size 32 free'd
==25784==    at 0x4C2DD8B: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==25784==    by 0x4365D0: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:145)
==25784==    by 0x429416: deallocate (allocator.h:211)
==25784==    by 0x429416: std::string::_Rep::_M_destroy(std::allocator<char> const&) (basic_string.tcc:880)
==25784==    by 0x425A9C: std::string::_Rep::_M_dispose(std::allocator<char> const&) (basic_string.h:3351)
==25784==    by 0x423DC1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (basic_string.h:3766)
==25784==    by 0x5C72E1: tao::graphqlpeg::internal::memory_input_base<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input_base() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C72FD: tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C7875: graphql::peg::depth_limit_input<tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string> >::~depth_limit_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A74DB: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784==  Block was alloc'd at
==25784==    at 0x4C2B788: operator new(unsigned long) (vg_replace_malloc.c:417)
==25784==    by 0x4365A6: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:127)
==25784==    by 0x4292CA: allocate (allocator.h:197)
==25784==    by 0x4292CA: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:1048)
==25784==    by 0x430012: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:610)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x5C607F: std::literals::string_literals::operator"" s(char const*, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A7433: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784== 
==25784== 
==25784== HEAP SUMMARY:
==25784==     in use at exit: 8,151 bytes in 215 blocks
==25784==   total heap usage: 1,264 allocs, 1,049 frees, 105,252 bytes allocated
==25784== 
==25784== LEAK SUMMARY:
==25784==    definitely lost: 0 bytes in 0 blocks
==25784==    indirectly lost: 0 bytes in 0 blocks
==25784==      possibly lost: 0 bytes in 0 blocks
==25784==    still reachable: 8,151 bytes in 215 blocks
==25784==         suppressed: 0 bytes in 0 blocks
==25784== Reachable blocks (those to which a pointer was found) are not shown.
==25784== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==25784== 
==25784== ERROR SUMMARY: 8 errors from 3 contexts (suppressed: 0 from 0)
==25784== 
==25784== 2 errors in context 1 of 3:
==25784== Invalid read of size 1
==25784==    at 0x4C322E0: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
==25784==    by 0x421F9C: std::char_traits<char>::copy(char*, char const*, unsigned long) (char_traits.h:409)
==25784==    by 0x42952F: std::string::_M_copy(char*, char const*, unsigned long) (basic_string.h:3463)
==25784==    by 0x436680: std::string::_S_copy_chars(char*, char const*, char const*) (basic_string.h:3510)
==25784==    by 0x430038: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:612)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x44B3DD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string::__sv_wrapper, std::allocator<char> const&) (basic_string.h:3569)
==25784==    by 0x44AC7D: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) (basic_string.h:3759)
==25784==    by 0x4A58B4: tao::graphqlpeg::position::position<std::basic_string_view<char, std::char_traits<char> > const&>(tao::graphqlpeg::internal::iterator const&, std::basic_string_view<char, std::char_traits<char> > const&) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x49E710: tao::graphqlpeg::parse_tree::basic_node<graphql::peg::ast_node, std::basic_string_view<char, std::char_traits<char> > >::begin() const (in /home/fantasy/next/graphql-server/build/main)
==25784==  Address 0x6070bbe is 30 bytes inside a block of size 32 free'd
==25784==    at 0x4C2DD8B: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==25784==    by 0x4365D0: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:145)
==25784==    by 0x429416: deallocate (allocator.h:211)
==25784==    by 0x429416: std::string::_Rep::_M_destroy(std::allocator<char> const&) (basic_string.tcc:880)
==25784==    by 0x425A9C: std::string::_Rep::_M_dispose(std::allocator<char> const&) (basic_string.h:3351)
==25784==    by 0x423DC1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (basic_string.h:3766)
==25784==    by 0x5C72E1: tao::graphqlpeg::internal::memory_input_base<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input_base() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C72FD: tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C7875: graphql::peg::depth_limit_input<tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string> >::~depth_limit_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A74DB: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784==  Block was alloc'd at
==25784==    at 0x4C2B788: operator new(unsigned long) (vg_replace_malloc.c:417)
==25784==    by 0x4365A6: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:127)
==25784==    by 0x4292CA: allocate (allocator.h:197)
==25784==    by 0x4292CA: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:1048)
==25784==    by 0x430012: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:610)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x5C607F: std::literals::string_literals::operator"" s(char const*, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A7433: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784== 
==25784== 
==25784== 2 errors in context 2 of 3:
==25784== Invalid read of size 2
==25784==    at 0x4C320EF: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
==25784==    by 0x421F9C: std::char_traits<char>::copy(char*, char const*, unsigned long) (char_traits.h:409)
==25784==    by 0x42952F: std::string::_M_copy(char*, char const*, unsigned long) (basic_string.h:3463)
==25784==    by 0x436680: std::string::_S_copy_chars(char*, char const*, char const*) (basic_string.h:3510)
==25784==    by 0x430038: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:612)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x44B3DD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string::__sv_wrapper, std::allocator<char> const&) (basic_string.h:3569)
==25784==    by 0x44AC7D: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) (basic_string.h:3759)
==25784==    by 0x4A58B4: tao::graphqlpeg::position::position<std::basic_string_view<char, std::char_traits<char> > const&>(tao::graphqlpeg::internal::iterator const&, std::basic_string_view<char, std::char_traits<char> > const&) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x49E710: tao::graphqlpeg::parse_tree::basic_node<graphql::peg::ast_node, std::basic_string_view<char, std::char_traits<char> > >::begin() const (in /home/fantasy/next/graphql-server/build/main)
==25784==  Address 0x6070bbc is 28 bytes inside a block of size 32 free'd
==25784==    at 0x4C2DD8B: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==25784==    by 0x4365D0: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:145)
==25784==    by 0x429416: deallocate (allocator.h:211)
==25784==    by 0x429416: std::string::_Rep::_M_destroy(std::allocator<char> const&) (basic_string.tcc:880)
==25784==    by 0x425A9C: std::string::_Rep::_M_dispose(std::allocator<char> const&) (basic_string.h:3351)
==25784==    by 0x423DC1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (basic_string.h:3766)
==25784==    by 0x5C72E1: tao::graphqlpeg::internal::memory_input_base<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input_base() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C72FD: tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C7875: graphql::peg::depth_limit_input<tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string> >::~depth_limit_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A74DB: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784==  Block was alloc'd at
==25784==    at 0x4C2B788: operator new(unsigned long) (vg_replace_malloc.c:417)
==25784==    by 0x4365A6: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:127)
==25784==    by 0x4292CA: allocate (allocator.h:197)
==25784==    by 0x4292CA: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:1048)
==25784==    by 0x430012: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:610)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x5C607F: std::literals::string_literals::operator"" s(char const*, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A7433: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784== 
==25784== 
==25784== 4 errors in context 3 of 3:
==25784== Invalid read of size 2
==25784==    at 0x4C320E0: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
==25784==    by 0x421F9C: std::char_traits<char>::copy(char*, char const*, unsigned long) (char_traits.h:409)
==25784==    by 0x42952F: std::string::_M_copy(char*, char const*, unsigned long) (basic_string.h:3463)
==25784==    by 0x436680: std::string::_S_copy_chars(char*, char const*, char const*) (basic_string.h:3510)
==25784==    by 0x430038: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:612)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x44B3DD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string::__sv_wrapper, std::allocator<char> const&) (basic_string.h:3569)
==25784==    by 0x44AC7D: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::basic_string_view<char, std::char_traits<char> >, void>(std::basic_string_view<char, std::char_traits<char> > const&, std::allocator<char> const&) (basic_string.h:3759)
==25784==    by 0x4A58B4: tao::graphqlpeg::position::position<std::basic_string_view<char, std::char_traits<char> > const&>(tao::graphqlpeg::internal::iterator const&, std::basic_string_view<char, std::char_traits<char> > const&) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x49E710: tao::graphqlpeg::parse_tree::basic_node<graphql::peg::ast_node, std::basic_string_view<char, std::char_traits<char> > >::begin() const (in /home/fantasy/next/graphql-server/build/main)
==25784==  Address 0x6070bb8 is 24 bytes inside a block of size 32 free'd
==25784==    at 0x4C2DD8B: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==25784==    by 0x4365D0: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:145)
==25784==    by 0x429416: deallocate (allocator.h:211)
==25784==    by 0x429416: std::string::_Rep::_M_destroy(std::allocator<char> const&) (basic_string.tcc:880)
==25784==    by 0x425A9C: std::string::_Rep::_M_dispose(std::allocator<char> const&) (basic_string.h:3351)
==25784==    by 0x423DC1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (basic_string.h:3766)
==25784==    by 0x5C72E1: tao::graphqlpeg::internal::memory_input_base<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input_base() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C72FD: tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string>::~memory_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5C7875: graphql::peg::depth_limit_input<tao::graphqlpeg::memory_input<(tao::graphqlpeg::tracking_mode)0, tao::graphqlpeg::ascii::eol::lf_crlf, std::string> >::~depth_limit_input() (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A74DB: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784==  Block was alloc'd at
==25784==    at 0x4C2B788: operator new(unsigned long) (vg_replace_malloc.c:417)
==25784==    by 0x4365A6: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:127)
==25784==    by 0x4292CA: allocate (allocator.h:197)
==25784==    by 0x4292CA: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:1048)
==25784==    by 0x430012: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (basic_string.tcc:610)
==25784==    by 0x429467: char* std::string::_S_construct_aux<char const*>(char const*, char const*, std::allocator<char> const&, std::__false_type) (basic_string.h:5178)
==25784==    by 0x425B16: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&) (basic_string.h:5199)
==25784==    by 0x44AA55: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (basic_string.h:3648)
==25784==    by 0x5C607F: std::literals::string_literals::operator"" s(char const*, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x5A7433: graphql::peg::parseString(std::basic_string_view<char, std::char_traits<char> >, unsigned long) (in /home/fantasy/next/graphql-server/build/main)
==25784==    by 0x45FD83: main (main.cpp:27)
==25784== 
==25784== ERROR SUMMARY: 8 errors from 3 contexts (suppressed: 0 from 0)
@wravery
Copy link
Contributor

wravery commented May 19, 2022

Thanks for the detailed report!

This looks like a use-after-free in the source name for the string, which parseString fills in with a std::string using "GraphQL"s. The lifetime of that source is tied to the lifetime of the memory_input<>, which is a temporary variable that is deleted after the parse completes.

I think that this was caused by adding the s literal to "GraphQL". Before, it would have used a static string literal with a static character pointer, and the template parameter for the memory_input<..., Source> would have been deduced from the constructor argument. The fix is probably just to revert to using a const char* parameter to the constructor.

wravery added a commit to wravery/cppgraphqlgen that referenced this issue May 19, 2022
@nqf
Copy link
Author

nqf commented May 19, 2022

Thanks for the detailed report!

This looks like a use-after-free in the source name for the string, which parseString fills in with a std::string using "GraphQL"s. The lifetime of that source is tied to the lifetime of the memory_input<>, which is a temporary variable that is deleted after the parse completes.

I think that this was caused by adding the s literal to "GraphQL". Before, it would have used a static string literal with a static character pointer, and the template parameter for the memory_input<..., Source> would have been deduced from the constructor argument. The fix is probably just to revert to using a const char* parameter to the constructor.

thanks, At present, I am trying to build a graphql service, It gets "({human(id: "1000") {name}})" from HTTP body, Then call graphql::peg::parseString

@wravery
Copy link
Contributor

wravery commented May 19, 2022

thanks, At present, I am trying to build a graphql service, It gets "({human(id: "1000") {name}})" from HTTP body, Then call graphql::peg::parseString

Right now it's being overly aggressive about trying to interpret the ID argument as a Base64 encoded string. The string "1000" is a valid Base64 encoding, so it assumes this is a binary ID rather than a string ID. Combined with a bug in the response::IdType::operator< overload when comparing binary data with strings, it also breaks lookups in a std::map<reponse::IdType, ...>, which showed up in my own learn_star_wars command line sample I used to debug this (using the query {human(id:"1001"){name id}}). I think I fixed both of those issues in the same branch as the valgrind error. I'll merge that back to main sometime today.

While you're waiting for those fixes, you can force the response::IdType argument to be interpreted as a string by calling argId.release<std::string>(), which will empty the argument variable and convert it back to the Base64 encoding of the bytes it's holding in a std::vector<std::uint8_t>, and that should match the original ID that you passed in the query. Once the fixes are in, the same call will work, or you can use the c_str() accessor since argId will be a string again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants