Skip to content

Commit

Permalink
Add SyntaxErr, so invalid hex conversions can be caught
Browse files Browse the repository at this point in the history
  • Loading branch information
aqk committed Mar 22, 2023
1 parent bf1a89e commit 990fd8c
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 37 deletions.
30 changes: 20 additions & 10 deletions src/classic/clvm/__type_compatibility__.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use sha2::Digest;
use sha2::Sha256;

use crate::util::Number;
//use crate::classic::clvm::__type_compatibility__::SyntaxErr;
use crate::classic::clvm::syntax_error::SyntaxErr;

pub fn to_hexstr(r: &[u8]) -> String {
hex::encode(r)
Expand Down Expand Up @@ -81,8 +83,11 @@ pub fn pybytes_repr(r: &[u8], dquoted: bool) -> String {
s
}

pub enum BytesFromType {
pub enum UnvalidatedBytesFromType {
Hex(String),
}

pub enum BytesFromType {
Raw(Vec<u8>),
String(String),
G1Element(G1Affine),
Expand Down Expand Up @@ -117,7 +122,15 @@ impl Bytes {
}
Bytes::new(Some(BytesFromType::Raw(bvec)))
}
Some(BytesFromType::Hex(hstr)) => {
Some(BytesFromType::G1Element(g1)) => Bytes {
_b: g1.to_uncompressed().to_vec(),
},
}
}

pub fn new_validated(value: Option<UnvalidatedBytesFromType>) -> Result<Self, SyntaxErr> {
match value {
Some(UnvalidatedBytesFromType::Hex(hstr)) => {
#[allow(clippy::single_char_pattern)]
let hex_stripped = hstr
.replace(" ", "")
Expand All @@ -126,16 +139,13 @@ impl Bytes {
.replace("\n", "");

match hex::decode(&hex_stripped) {
Ok(d) => Bytes { _b: d },
Err(e) => {
eprintln!("{} in '{}'", e, hex_stripped);
std::process::exit(1);
}
Ok(d) => Ok(Bytes { _b: d }),
Err(e) => Err(SyntaxErr {
msg: format!("{} in '{}'", e, hex_stripped),
}),
}
}
Some(BytesFromType::G1Element(g1)) => Bytes {
_b: g1.to_uncompressed().to_vec(),
},
None => Ok(Bytes { _b: vec![] }),
}
}

Expand Down
1 change: 1 addition & 0 deletions src/classic/clvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod casts;
pub mod costs;
pub mod serialize;
pub mod sexp;
pub mod syntax_error;

struct KwAtomPair {
v: u8,
Expand Down
40 changes: 30 additions & 10 deletions src/classic/clvm_tools/cmds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use clvm_rs::allocator::{Allocator, NodePtr};
use clvm_rs::reduction::EvalErr;
use clvm_rs::run_program::PreEval;

use crate::classic::clvm::__type_compatibility__::{t, Bytes, BytesFromType, Stream, Tuple};
use crate::classic::clvm::__type_compatibility__::{
t, Bytes, BytesFromType, Stream, Tuple, UnvalidatedBytesFromType,
};
use crate::classic::clvm::keyword_from_atom;
use crate::classic::clvm::serialize::{sexp_from_stream, sexp_to_stream, SimpleCreateCLVMObject};
use crate::classic::clvm::sexp::{enlist, proper_list, sexp_as_bin};
Expand Down Expand Up @@ -228,9 +230,12 @@ impl TConversion for OpdConversion {
allocator: &mut Allocator,
hex_text: &str,
) -> Result<Tuple<NodePtr, String>, String> {
let mut stream = Stream::new(Some(Bytes::new(Some(BytesFromType::Hex(
hex_text.to_string(),
)))));
let mut stream = Stream::new(Some(
match Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(hex_text.to_string()))) {
Ok(x) => x,
Err(e) => return Err(e.to_string()),
},
));

sexp_from_stream(allocator, &mut stream, Box::new(SimpleCreateCLVMObject {}))
.map_err(|e| e.1)
Expand Down Expand Up @@ -851,18 +856,33 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul

match parsed_args.get("hex") {
Some(_) => {
let assembled_serialized =
Bytes::new(Some(BytesFromType::Hex(input_program.to_string())));
let assembled_serialized = Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(
input_program.to_string(),
)));

let env_serialized = if input_args.is_empty() {
Bytes::new(Some(BytesFromType::Hex("80".to_string())))
Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex("80".to_string())))
} else {
Bytes::new(Some(BytesFromType::Hex(input_args)))
Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(input_args)))
};

let ee = match env_serialized {
Ok(x) => x,
Err(e) => {
stdout.write_str(&format!("FAIL: {e}\n"));
return;
}
};
time_read_hex = SystemTime::now();

let mut prog_stream = Stream::new(Some(assembled_serialized));
let mut prog_stream = Stream::new(Some(match assembled_serialized {
Ok(x) => x,
Err(e) => {
stdout.write_str(&format!("FAIL: {e}\n"));
return;
}
}));

let input_prog_sexp = sexp_from_stream(
&mut allocator,
&mut prog_stream,
Expand All @@ -871,7 +891,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul
.map(|x| Some(x.1))
.unwrap();

let mut arg_stream = Stream::new(Some(env_serialized));
let mut arg_stream = Stream::new(Some(ee));
let input_arg_sexp = sexp_from_stream(
&mut allocator,
&mut arg_stream,
Expand Down
42 changes: 29 additions & 13 deletions src/classic/clvm_tools/ir/reader.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::mem::swap;
use std::rc::Rc;

use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType, Stream};
use crate::classic::clvm::__type_compatibility__::{
Bytes, BytesFromType, Stream, UnvalidatedBytesFromType,
};
use crate::classic::clvm::casts::bigint_to_bytes_clvm;
use crate::classic::clvm::syntax_error::SyntaxErr;
use crate::classic::clvm_tools::ir::r#type::IRRepr;
use crate::util::Number;

Expand Down Expand Up @@ -129,49 +132,61 @@ pub fn is_dec(chars: &[u8]) -> bool {
true
}

pub fn interpret_atom_value(chars: &[u8]) -> IRRepr {
pub fn interpret_atom_value(chars: &[u8]) -> Result<IRRepr, SyntaxErr> {
if chars.is_empty() {
IRRepr::Null
Ok(IRRepr::Null)
} else if is_hex(chars) {
let mut string_bytes = if chars.len() % 2 > 0 {
Bytes::new(Some(BytesFromType::Raw(vec![b'0'])))
} else {
// hmm ...
Bytes::new(None)
};
string_bytes =
string_bytes.concat(&Bytes::new(Some(BytesFromType::Raw(chars[2..].to_vec()))));

IRRepr::Hex(Bytes::new(Some(BytesFromType::Hex(string_bytes.decode()))))
Ok(IRRepr::Hex(
match Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(string_bytes.decode()))) {
Ok(x) => x,
Err(e) => return Err(SyntaxErr { msg: e.to_string() }),
},
))
} else {
match String::from_utf8(chars.to_vec())
.ok()
.and_then(|s| s.parse::<Number>().ok())
.map(|n| bigint_to_bytes_clvm(&n))
{
Some(n) => IRRepr::Int(n, true),
Some(n) => Ok(IRRepr::Int(n, true)),
None => {
let string_bytes = Bytes::new(Some(BytesFromType::Raw(chars.to_vec())));
IRRepr::Symbol(string_bytes.decode())
Ok(IRRepr::Symbol(string_bytes.decode()))
}
}
}
}

pub fn consume_atom(s: &mut IRReader, b: &Bytes) -> Option<IRRepr> {
pub fn consume_atom(s: &mut IRReader, b: &Bytes) -> Result<Option<IRRepr>, SyntaxErr> {
let mut result_vec = b.data().to_vec();
loop {
let b = s.read(1);
if b.length() == 0 {
if result_vec.is_empty() {
return None;
return Ok(None);
} else {
return Some(interpret_atom_value(&result_vec));
return Ok(Some(match interpret_atom_value(&result_vec) {
Ok(x) => x,
Err(e) => return Err(SyntaxErr { msg: e.to_string() }),
}));
}
}

if b.at(0) == b'(' || b.at(0) == b')' || is_space(b.at(0)) {
s.backup(1);
return Some(interpret_atom_value(&result_vec));
return Ok(Some(match interpret_atom_value(&result_vec) {
Ok(x) => x,
Err(e) => return Err(SyntaxErr { msg: e.to_string() }),
}));
}

result_vec.push(b.at(0));
Expand Down Expand Up @@ -246,7 +261,7 @@ pub fn consume_cons_body(s: &mut IRReader) -> Result<IRRepr, String> {
}
} else {
match consume_atom(s, &b) {
Some(f) => {
Ok(Some(f)) => {
result.push(f);
continue;
}
Expand All @@ -270,8 +285,9 @@ pub fn consume_object(s: &mut IRReader) -> Result<IRRepr, String> {
consume_quoted(s, b.at(0) as char)
} else {
match consume_atom(s, &b) {
None => Err("empty stream".to_string()),
Some(ir) => Ok(ir),
Ok(None) => Err("empty stream".to_string()),
Ok(Some(ir)) => Ok(ir),
Err(e) => Err(e.to_string()),
}
}
}
Expand Down
15 changes: 13 additions & 2 deletions src/compiler/cldb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ use clvm_rs::allocator::{Allocator, NodePtr};
use clvm_rs::reduction::EvalErr;
use num_bigint::ToBigInt;

use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType, Stream};
use crate::classic::clvm::__type_compatibility__::{
Bytes, BytesFromType, Stream, UnvalidatedBytesFromType,
};
use crate::classic::clvm::serialize::{sexp_from_stream, SimpleCreateCLVMObject};
//use crate::classic::clvm::syntax_error::SyntaxErr;
use crate::classic::clvm_tools::sha256tree::sha256tree;
use crate::classic::clvm_tools::stages::stage_0::TRunProgram;

Expand Down Expand Up @@ -505,7 +508,15 @@ pub fn hex_to_modern_sexp(
loc: Srcloc,
input_program: &str,
) -> Result<Rc<SExp>, RunFailure> {
let input_serialized = Bytes::new(Some(BytesFromType::Hex(input_program.to_string())));
let input_serialized = match Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(
input_program.to_string(),
))) {
Ok(x) => x,
Err(e) => {
// TODO: Should be SyntaxErr ?
return Err(RunFailure::RunErr(loc, e.to_string()));
}
};

let mut stream = Stream::new(Some(input_serialized));
let sexp = sexp_from_stream(allocator, &mut stream, Box::new(SimpleCreateCLVMObject {}))
Expand Down
13 changes: 11 additions & 2 deletions src/py/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::thread;

use clvm_rs::allocator::Allocator;

use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType, Stream};
use crate::classic::clvm::__type_compatibility__::{Bytes, Stream, UnvalidatedBytesFromType};
use crate::classic::clvm::serialize::sexp_to_stream;
use crate::classic::clvm_tools::clvmc;
use crate::classic::clvm_tools::cmds;
Expand Down Expand Up @@ -356,7 +356,16 @@ pub fn compose_run_function(
)));
}
};
let hash_bytes = Bytes::new(Some(BytesFromType::Hex(function_hash.clone())));
let hash_bytes =
match Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(function_hash.clone()))) {
Ok(x) => x,
Err(e) => {
return Err(compile_err_to_cldb_err(&CompileErr(
program.loc(),
format!("bad function hash: ({}) {}", function_hash, e),
)));
}
};
let function_path = match path_to_function(main_env.1.clone(), &hash_bytes.data().clone()) {
Some(p) => p,
_ => {
Expand Down

0 comments on commit 990fd8c

Please sign in to comment.