From 190e2d138540e9050dbdcced6e2d6b7ec69a500c Mon Sep 17 00:00:00 2001 From: John Turpish Date: Thu, 14 Dec 2023 14:30:24 -0500 Subject: [PATCH] Fixes #85 Removing code for absolute symlinks which point outside root. --- library/include/ipfs_client/multi_hash.h | 2 + .../libp2p/multi/content_identifier.hpp | 46 --------- .../libp2p/multi/content_identifier_codec.hpp | 99 ------------------- library/src/ipfs_client/cid.cc | 2 +- library/src/ipfs_client/dag_block_unittest.cc | 2 +- library/src/ipfs_client/identity_cid.cc | 5 +- library/src/ipfs_client/ipld/symlink.cc | 61 +++--------- library/src/ipfs_client/ipld/symlink.h | 9 +- .../src/ipfs_client/ipld/symlink_unittest.cc | 32 ------ 9 files changed, 20 insertions(+), 238 deletions(-) delete mode 100644 library/include/libp2p/multi/content_identifier.hpp delete mode 100644 library/include/libp2p/multi/content_identifier_codec.hpp diff --git a/library/include/ipfs_client/multi_hash.h b/library/include/ipfs_client/multi_hash.h index 1d998fa0..8d0a06a3 100644 --- a/library/include/ipfs_client/multi_hash.h +++ b/library/include/ipfs_client/multi_hash.h @@ -7,6 +7,8 @@ namespace ipfs { enum class HashType { INVALID = -1, IDENTITY = 0, SHA2_256 = 0X12 }; +constexpr std::uint16_t MaximumHashLength = 127; + HashType Validate(HashType); std::string_view GetName(HashType); class MultiHash { diff --git a/library/include/libp2p/multi/content_identifier.hpp b/library/include/libp2p/multi/content_identifier.hpp deleted file mode 100644 index d677ddf3..00000000 --- a/library/include/libp2p/multi/content_identifier.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef LIBP2P_CONTENT_IDENTIFIER_HPP -#define LIBP2P_CONTENT_IDENTIFIER_HPP - -#include - -#include -#include -#include - -namespace libp2p::multi { - -/** - * A CID is a self-describing content-addressed identifier. It uses - * cryptographic hashes to achieve content addressing. It uses several - * multiformats to achieve flexible self-description, namely multihash for - * hashes, multicodec for data content types, and multibase to encode the CID - * itself into strings. Concretely, it's a typed content address: a tuple of - * (content-type, content-address). - * - * @note multibase may be omitted in non text-based protocols and is generally - * needed only for CIDs serialized to a string, so it is not present in this - * structure - */ -struct ContentIdentifier { - enum class Version { V0 = 0, V1 = 1 }; - - ContentIdentifier(Version version, - MulticodecType::Code content_type, - Multihash content_address); - - bool operator==(const ContentIdentifier& c) const; - bool operator<(const ContentIdentifier& c) const; - - Version version; - MulticodecType::Code content_type; - Multihash content_address; -}; - -} // namespace libp2p::multi - -#endif // LIBP2P_CONTENT_IDENTIFIER_HPP diff --git a/library/include/libp2p/multi/content_identifier_codec.hpp b/library/include/libp2p/multi/content_identifier_codec.hpp deleted file mode 100644 index 197223fd..00000000 --- a/library/include/libp2p/multi/content_identifier_codec.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef LIBP2P_CONTENT_IDENTIFIER_CODEC_HPP -#define LIBP2P_CONTENT_IDENTIFIER_CODEC_HPP - -#include -#include - -namespace libp2p::multi { - -/** - * Serializes and deserializes CID to byte representation. - * To serialize it to a multibase encoded string, use MultibaseCodec - * @see MultibaseCodec - */ -class ContentIdentifierCodec { - public: - enum class EncodeError { - INVALID_CONTENT_TYPE = 1, - INVALID_HASH_TYPE, - INVALID_HASH_LENGTH, - VERSION_UNSUPPORTED, - INVALID_BASE_ENCODING, - }; - - enum class DecodeError { - EMPTY_VERSION = 1, - EMPTY_MULTICODEC, - MALFORMED_VERSION, - RESERVED_VERSION, - CID_TOO_SHORT, - BAD_MULTIHASH, - BAD_MULTIBASE, - UNSUPPORTED_MULTIBASE - }; - - static ipfs::expected, EncodeError> encode( - const ContentIdentifier& cid); - - /// Encodes arbitrary byte buffer into CID v.0 wire format - static std::vector encodeCIDV0(const void* byte_buffer, - size_t sz); - - /// Encodes arbitrary byte buffer into CID v.1 wire format - static std::vector encodeCIDV1(MulticodecType::Code content_type, - const Multihash& mhash); - - static ipfs::expected decode( - ipfs::ByteView bytes); - - /** - * @brief Encode CID to string representation - * @param cid - input CID for encode - * Encoding: - * Base58 for CID v0 - * Base32 for CID v1 - * @return CID string - */ - static ipfs::expected toString( - const ContentIdentifier& cid); - - /** - * @brief Encode CID to string representation - * @param cid - input CID for encode - * @param base - type of the encoding - * @return CID string - */ - static ipfs::expected toStringOfBase( - const ContentIdentifier& cid, - MultibaseCodec::Encoding base); - - /** - * @brief Decode string representation of CID to CID - * @param str - CID string representation - * @return CID - */ - static ipfs::expected fromString( - std::string_view str); -}; - -std::string_view Stringify(libp2p::multi::ContentIdentifierCodec::DecodeError); - -} // namespace libp2p::multi - -std::ostream& operator<<(std::ostream&, - libp2p::multi::ContentIdentifierCodec::EncodeError); -std::ostream& operator<<(std::ostream&, - libp2p::multi::ContentIdentifierCodec::DecodeError); - -#include -// OUTCOME_HPP_DECLARE_ERROR(libp2p::multi, -// ContentIdentifierCodec::EncodeError); -// OUTCOME_HPP_DECLARE_ERROR(libp2p::multi, -// ContentIdentifierCodec::DecodeError); - -#endif // LIBP2P_CONTENT_IDENTIFIER_CODEC_HPP diff --git a/library/src/ipfs_client/cid.cc b/library/src/ipfs_client/cid.cc index a961c0c6..f94539e6 100644 --- a/library/src/ipfs_client/cid.cc +++ b/library/src/ipfs_client/cid.cc @@ -24,7 +24,7 @@ Self::Cid(std::string_view s) { assign(bytes.value()); } } else { - LOG(ERROR) << "Failed to decode the multibase for a CID: " << s; + LOG(WARNING) << "Failed to decode the multibase for a CID: " << s; } } diff --git a/library/src/ipfs_client/dag_block_unittest.cc b/library/src/ipfs_client/dag_block_unittest.cc index c3b41535..177b2e50 100644 --- a/library/src/ipfs_client/dag_block_unittest.cc +++ b/library/src/ipfs_client/dag_block_unittest.cc @@ -99,4 +99,4 @@ TEST(BlockTest, TypeNames) { EXPECT_EQ(Stringify(T::FileChunk), "FileChunk"); EXPECT_EQ(Stringify(T::NonFs), "NonFs"); EXPECT_EQ(Stringify(T::Invalid), "Invalid"); -} \ No newline at end of file +} diff --git a/library/src/ipfs_client/identity_cid.cc b/library/src/ipfs_client/identity_cid.cc index 9a1ca6b8..9ea2421d 100644 --- a/library/src/ipfs_client/identity_cid.cc +++ b/library/src/ipfs_client/identity_cid.cc @@ -1,14 +1,11 @@ #include -#include - #include namespace Self = ipfs::id_cid; -namespace m = libp2p::multi; auto Self::forText(std::string_view txt) -> Cid { - txt = txt.substr(0UL, m::Multihash::kMaxHashLength); + txt = txt.substr(0UL, MaximumHashLength); auto p = reinterpret_cast(txt.data()); auto b = ByteView{p, txt.size()}; MultiHash mh(HashType::IDENTITY, b); diff --git a/library/src/ipfs_client/ipld/symlink.cc b/library/src/ipfs_client/ipld/symlink.cc index 8c65e276..8740ed70 100644 --- a/library/src/ipfs_client/ipld/symlink.cc +++ b/library/src/ipfs_client/ipld/symlink.cc @@ -4,33 +4,24 @@ using Self = ipfs::ipld::Symlink; -Self::Symlink(std::string target) - : style_{from_target(target)}, target_{target} {} +Self::Symlink(std::string target) : target_{target} {} Self::~Symlink() {} auto Self::resolve(SlashDelimited path, BlockLookup, std::string& to_here) -> ResolveResult { std::string result; - switch (style_) { - case Style::Absolute: - result.assign(target_); - LOG(INFO) << "Absolute symlink '" << target_ << "' ..."; - break; - case Style::Relative: { - auto c = to_here.find_last_not_of('/'); - c = to_here.find_last_of('/', c); - DCHECK(c != to_here.size()) << to_here; + if (is_absolute()) { + result.assign(SlashDelimited{to_here}.pop_n(2)).append("/").append(target_); + LOG(INFO) << "Absolute (relative-to-dag-root) symlink '" << target_ + << "' leads to '" << result << "' ... "; + } else { + auto c = to_here.find_last_not_of('/'); + c = to_here.find_last_of('/', c); + DCHECK(c != to_here.size()) << to_here; result.assign(to_here, 0, c + 1).append(target_); LOG(INFO) << "Relative symlink '" << target_ << "' leads to '" << result << "' ... "; - } break; - case Style::FromRoot: - result.assign(SlashDelimited{to_here}.pop_n(2)) - .append("/") - .append(target_); - LOG(INFO) << "Relative-to-root symlink '" << target_ << "' leads to '" - << result << "' ... "; } if (path) { result.append("/").append(path.pop_all()); @@ -43,36 +34,10 @@ auto Self::resolve(SlashDelimited path, BlockLookup, std::string& to_here) if (result.back() == '/') { result.resize(result.size() - 1); } - LOG(WARNING) << "symlink: '" << to_here << "' -> '" << result << "'."; + LOG(INFO) << "symlink: '" << to_here << "' -> '" << result << "'."; return PathChange{result}; } -auto Self::from_target(std::string const& target) -> Style { - DCHECK_GT(target.size(), 0U); - if (target.at(0) != '/') { - return Style::Relative; - } - SlashDelimited t{target}; - auto ns = t.pop(); - if (ns != "ipfs" && ns != "ipns") { - return Style::FromRoot; - } - auto root = t.pop(); - using namespace libp2p::multi; - auto cid = Cid(root); - if (!cid.valid()) { - if (ns == "ipns") { - LOG(WARNING) << "Symlink to DNSLink is highly irregular."; - return Style::Absolute; - } else { - LOG(WARNING) << "Someone has a subdirectory of their DAG root that is " - "called /ipfs/ ? Who does that?"; - return Style::FromRoot; - } - } - if (cid.codec() == MultiCodec::LIBP2P_KEY) { - return ns == "ipns" ? Style::Absolute : Style::FromRoot; - } else { - return ns == "ipfs" ? Style::Absolute : Style::FromRoot; - } -} +bool Self::is_absolute() const { + return target_.at(0) == '/'; +} \ No newline at end of file diff --git a/library/src/ipfs_client/ipld/symlink.h b/library/src/ipfs_client/ipld/symlink.h index 84917ddd..0ef7b23d 100644 --- a/library/src/ipfs_client/ipld/symlink.h +++ b/library/src/ipfs_client/ipld/symlink.h @@ -5,19 +5,14 @@ namespace ipfs::ipld { class Symlink : public DagNode { - enum class Style { - Relative, - Absolute, - FromRoot, - }; - Style const style_; std::string const target_; - Style from_target(std::string const&); ResolveResult resolve(SlashDelimited path, BlockLookup, std::string& up_to_here) override; + bool is_absolute() const; + public: Symlink(std::string target); ~Symlink() noexcept override; diff --git a/library/src/ipfs_client/ipld/symlink_unittest.cc b/library/src/ipfs_client/ipld/symlink_unittest.cc index 1482a702..5413ebf6 100644 --- a/library/src/ipfs_client/ipld/symlink_unittest.cc +++ b/library/src/ipfs_client/ipld/symlink_unittest.cc @@ -27,23 +27,6 @@ TEST(SymlinkTest, fromBlock) { "a/d/e"; EXPECT_EQ(actual.new_path, expect); } -TEST(SymlinkTest, absolute) { - ii::Symlink sub{ - "/ipfs/bafkreih6wk34z7qlwe2jj4ynowkh4ux6pbqnijcebcz7sd4fz3rnigxa6u"}; - ii::DagNode& t = sub; - auto blu = [](std::string const&) -> ii::NodePtr { - throw std::runtime_error{"Block lookup not expected."}; - }; - std::string observed_path_to_link{"/ipns/"}; - observed_path_to_link - .append("k51qzi5uqu5dkq4jxcqvujfm2woh4p9y6inrojofxflzdnfht168zf8ynfzuu1") - .append("symlinks/absolute_link.txt"); - auto res = t.resolve(""sv, blu, observed_path_to_link); - EXPECT_TRUE(std::holds_alternative(res)); - EXPECT_EQ( - std::get(res).new_path, - "/ipfs/bafkreih6wk34z7qlwe2jj4ynowkh4ux6pbqnijcebcz7sd4fz3rnigxa6u"); -} TEST(SymlinkTest, rooted) { ii::Symlink sub{"/another/path.txt"}; ii::DagNode& t = sub; @@ -61,18 +44,3 @@ TEST(SymlinkTest, rooted) { "/ipns/k51qzi5uqu5dkq4jxcqvujfm2woh4p9y6inrojofxflzdnfht168zf8ynfzuu1/" "another/path.txt"); } -TEST(SymlinkTest, ipns_absolute) { - ii::Symlink sub{"/ipns/en.wikipedia-on-ipfs.org"}; - ii::DagNode& t = sub; - auto blu = [](std::string const&) -> ii::NodePtr { - throw std::runtime_error{"Block lookup not expected."}; - }; - std::string observed_path_to_link{"/ipns/"}; - observed_path_to_link - .append("k51qzi5uqu5dkq4jxcqvujfm2woh4p9y6inrojofxflzdnfht168zf8ynfzuu1") - .append("symlinks/absolute_link.txt"); - auto res = t.resolve(""sv, blu, observed_path_to_link); - EXPECT_TRUE(std::holds_alternative(res)); - EXPECT_EQ(std::get(res).new_path, - "/ipns/en.wikipedia-on-ipfs.org"); -}