From 8a333100efd9494def26252911d92cc2063c76dc Mon Sep 17 00:00:00 2001 From: y Date: Sun, 17 Sep 2023 10:20:44 -0400 Subject: [PATCH] zkas: fix panic in Analyzer This issue was discovered with fuzzing. Panic 1: It was possible to assign a variable to a function/opcode with no return type. This caused a index-out-of-bounds panic when the analyzer attempted to access the first element of an empty vector of return types. The analyzer now presents an error when a .zk author attempts to assign a variable to an opcode that has no return types. Panic 2: There was an index-out-of-bounds panic when performing verification on Literals that were passed to Opcodes that use Array types as their arguments. This was fixed by pasting the validation code from the Variable verfication section which handles Arrays properly. (Refactoring should be done to reduce duplication here.) --- src/zkas/analyzer.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/zkas/analyzer.rs b/src/zkas/analyzer.rs index b734f9167..95665c0a4 100644 --- a/src/zkas/analyzer.rs +++ b/src/zkas/analyzer.rs @@ -253,7 +253,37 @@ impl Analyzer { if let Arg::Lit(v) = arg { // Match this literal type to a VarType for // type checking. + let var_type = v.typ.to_vartype(); + // TODO: Refactor the Array type checks here and in the Arg::Var + // section so that there is less repetition. + // Validation for Array types + if arg_types[0] == VarType::BaseArray { + if var_type != VarType::Base { + return Err(self.error.abort( + &format!( + "Incorrect argument type. Expected `{:?}`, got `{:?}`.", + VarType::Base, + var_type + ), + v.line, + v.column, + )) + } + } else if arg_types[0] == VarType::ScalarArray { + if var_type != VarType::Scalar { + return Err(self.error.abort( + &format!( + "Incorrect argument type. Expected `{:?}`, got `{:?}`.", + VarType::Scalar, + var_type + ), + v.line, + v.column, + )) + } + } + // Validation for non-Array types if var_type != arg_types[idx] { return Err(self.error.abort( &format!( @@ -337,6 +367,14 @@ impl Analyzer { // result on the heap. if statement.typ == StatementType::Assign { let mut var = statement.lhs.clone().unwrap(); + // Since we are doing an assignment, ensure that there is a return type. + if return_types.is_empty() { + return Err(self.error.abort( + "Cannot perform assignment without a return type", + var.line, + var.column, + )) + } var.typ = return_types[0]; stmt.lhs = Some(var.clone()); heap.push(var.clone());