1
0
mirror of https://github.com/oconnor663/bao synced 2025-02-21 23:21:05 +01:00
bao/tests/swap_content.py

45 lines
1.8 KiB
Python
Executable File

#! /usr/bin/python3
# ./swap_content.py <encoded_file>
#
# Reads input from stdin and replaces the content (but not the hashes!) of the
# encoded file with the stdin bytes. If stdin is shorter than the content, the
# remaining content bytes are unmodified. If stdin is longer, only the input up
# to the length of the encoded content is used. Either way, the encoded file
# length is unchanged.
#
# This tool is used to construct corrupted Bao encodings, for testing and
# demos. Normally any difference between two inputs would result in a different
# root node, so a decoder reading the wrong file will abort immediately with no
# output. However, it's possible that corruption in the tree only shows up
# halfway through, and in that case the decoder can emit valid output before
# encountering the corruption and aborting.
import bao
import sys
def swap_recurse(encoded_stream, input_stream, content_len):
if content_len <= bao.CHUNK_SIZE:
# We might get fewer input bytes than requested, if the input stream is
# finished. That's fine. All the writes after that point will be empty,
# and the rest of the tree will be left as is.
input_bytes = input_stream.read(content_len)
encoded_stream.write(input_bytes)
else:
# Read past the parent node and then recurse to the children.
encoded_stream.read(bao.PARENT_SIZE)
left_len = bao.left_len(content_len)
swap_recurse(encoded_stream, input_stream, left_len)
swap_recurse(encoded_stream, input_stream, content_len - left_len)
def main():
encoded_stream = open(sys.argv[1], "rb+")
content_len = bao.decode_len(encoded_stream.read(bao.HEADER_SIZE))
swap_recurse(encoded_stream, sys.stdin.buffer, content_len)
if __name__ == "__main__":
main()