From 2694a500787781ec237e39d9ab4e40aa6325572b Mon Sep 17 00:00:00 2001 From: Richard Kiss Date: Tue, 18 Jul 2023 16:11:12 -0700 Subject: [PATCH] Fix ROM deserializer bug. --- cl/chialisp_deserialisation.clsp | 72 ++++++++++++++++++++++++++++++++ src/generator_rom.rs | 4 +- 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 cl/chialisp_deserialisation.clsp diff --git a/cl/chialisp_deserialisation.clsp b/cl/chialisp_deserialisation.clsp new file mode 100644 index 000000000..63653d31e --- /dev/null +++ b/cl/chialisp_deserialisation.clsp @@ -0,0 +1,72 @@ +;; this code deserializes blobs of length up to 1<<20 = 1048576 bytes + +(mod (input) + + (defconstant MAX_SINGLE_BYTE 0x7F) + (defconstant MAX_TWO_BYTE 0xbf) + (defconstant MAX_THREE_BYTE 0xdf) + (defconstant MAX_FOUR_BYTE 0xef) + (defconstant MAX_FIVE_BYTE 0xf7) + (defconstant MAX_SIX_BYTE 0xfb) + (defconstant CONS_BOX_MARKER 0xFF) + + (defun sexp_from_stream (input_stream) + (if (= (substr input_stream 0 1) CONS_BOX_MARKER) + (cons_sexp_from_stream (sexp_from_stream (substr input_stream 1))) + (atom_from_stream (substr input_stream 1) (substr input_stream 0 1)) + ) + ) + + (defun cons_sexp_from_stream (left_sexp_with_input) + (cons_return (f left_sexp_with_input) (sexp_from_stream (f (r left_sexp_with_input)))) + ) + + (defun cons_return (left_sexp right_sexp_with_input) + (list (c left_sexp (f right_sexp_with_input)) (f (r right_sexp_with_input))) + ) + + (defun atom_from_stream (input_file input_bits) + (if (= input_bits (quote 0x80)) + (list () input_file) + (if (>s input_bits MAX_SINGLE_BYTE) + (atom_from_stream_part_two (get_bitcount input_bits input_file)) + (list input_bits input_file) + ) + ) + ) + + ; Note that we reject any serialized atom here with more than 4 bytes of + ; encoded length prefix, even though the Rust and Python CLVM interpreters + ; and deserializers support more. + ; This allows 6 + 7 + 7 = 20 bits = 1048576-byte atoms + ; Also note that this does not limit intermediate atom length. Those limits + ; are implemented in the clvm interpreters theselves + (defun-inline get_bitcount (input_bits input_file) + (if (>s input_bits MAX_TWO_BYTE) + (if (>s input_bits MAX_THREE_BYTE) + ; we don't use the constant here so costs are the same as the + ; original (buggy) version of this code which was limited + ; to 8192-byte atoms. + ; Adding the constant to the constant tree changes locations + ; of objects in the tree, which changes costs. + (if (>s input_bits (q . 0xef)) + (x) + ;four byte length prefix + (c (concat 0x00 (logand (quote 0x7) input_bits) (substr input_file 0 3)) (substr input_file 3)) + ) + ;three byte length prefix + (list (concat (logand (quote 0x1f) input_bits) (substr input_file 0 1)) (substr input_file 1)) + ) + ;two byte length prefix + (list (logand (quote 0x3f) input_bits) input_file) + ) + ) + + (defun atom_from_stream_part_two ((size_to_read input_file)) + (list (substr input_file 0 size_to_read) (substr input_file size_to_read)) + ) + + ; main + (f (sexp_from_stream input)) + +) diff --git a/src/generator_rom.rs b/src/generator_rom.rs index 92a545c90..03d8fa791 100644 --- a/src/generator_rom.rs +++ b/src/generator_rom.rs @@ -32,9 +32,9 @@ pub const GENERATOR_ROM: [u8; 737] = hex!( // the CLVM deserializer from: // https://github.com/Chia-Network/chia-blockchain/blob/main/chia/wallet/puzzles/chialisp_deserialisation.clsp.hex -pub const CLVM_DESERIALIZER: [u8; 471] = hex!( +pub const CLVM_DESERIALIZER: [u8; 498] = hex!( " -ff02ffff01ff05ffff02ff3effff04ff02ffff04ff05ff8080808080ffff04ffff01ffffff81ff7fff81df81bfffffff02ffff03ffff09ff0bffff01818080ffff01ff04ff80ffff04ff05ff808080ffff01ff02ffff03ffff0aff0bff1880ffff01ff02ff1affff04ff02ffff04ffff02ffff03ffff0aff0bff1c80ffff01ff02ffff03ffff0aff0bff1480ffff01ff0880ffff01ff04ffff0effff18ffff011fff0b80ffff0cff05ff80ffff01018080ffff04ffff0cff05ffff010180ff80808080ff0180ffff01ff04ffff18ffff013fff0b80ffff04ff05ff80808080ff0180ff80808080ffff01ff04ff0bffff04ff05ff80808080ff018080ff0180ff04ffff0cff15ff80ff0980ffff04ffff0cff15ff0980ff808080ffff04ffff04ff05ff1380ffff04ff2bff808080ffff02ff16ffff04ff02ffff04ff09ffff04ffff02ff3effff04ff02ffff04ff15ff80808080ff8080808080ff02ffff03ffff09ffff0cff05ff80ffff010180ff1080ffff01ff02ff2effff04ff02ffff04ffff02ff3effff04ff02ffff04ffff0cff05ffff010180ff80808080ff80808080ffff01ff02ff12ffff04ff02ffff04ffff0cff05ffff010180ffff04ffff0cff05ff80ffff010180ff808080808080ff0180ff018080" +ff02ffff01ff05ffff02ff3effff04ff02ffff04ff05ff8080808080ffff04ffff01ffffff81ff7fff81df81bfffffff02ffff03ffff09ff0bffff01818080ffff01ff04ff80ffff04ff05ff808080ffff01ff02ffff03ffff0aff0bff1880ffff01ff02ff1affff04ff02ffff04ffff02ffff03ffff0aff0bff1c80ffff01ff02ffff03ffff0aff0bff1480ffff01ff02ffff03ffff0aff0bffff0181ef80ff80ffff01ff0182776580ff0180ffff01ff04ffff0effff18ffff011fff0b80ffff0cff05ff80ffff01018080ffff04ffff0cff05ffff010180ff80808080ff0180ffff01ff04ffff18ffff013fff0b80ffff04ff05ff80808080ff0180ff80808080ffff01ff04ff0bffff04ff05ff80808080ff018080ff0180ff04ffff0cff15ff80ff0980ffff04ffff0cff15ff0980ff808080ffff04ffff04ff05ff1380ffff04ff2bff808080ffff02ff16ffff04ff02ffff04ff09ffff04ffff02ff3effff04ff02ffff04ff15ff80808080ff8080808080ff02ffff03ffff09ffff0cff05ff80ffff010180ff1080ffff01ff02ff2effff04ff02ffff04ffff02ff3effff04ff02ffff04ffff0cff05ffff010180ff80808080ff80808080ffff01ff02ff12ffff04ff02ffff04ffff0cff05ffff010180ffff04ffff0cff05ff80ffff010180ff808080808080ff0180ff018080" ); // constant from the main chia blockchain: