فهرست منبع

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.)
y 2 سال پیش
والد
کامیت
8a333100ef
1فایلهای تغییر یافته به همراه38 افزوده شده و 0 حذف شده
  1. 38 0
      src/zkas/analyzer.rs

+ 38 - 0
src/zkas/analyzer.rs

@@ -253,7 +253,37 @@ impl Analyzer {
                 if let Arg::Lit(v) = arg {
                 if let Arg::Lit(v) = arg {
                     // Match this literal type to a VarType for
                     // Match this literal type to a VarType for
                     // type checking.
                     // type checking.
+
                     let var_type = v.typ.to_vartype();
                     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] {
                     if var_type != arg_types[idx] {
                         return Err(self.error.abort(
                         return Err(self.error.abort(
                             &format!(
                             &format!(
@@ -337,6 +367,14 @@ impl Analyzer {
             // result on the heap.
             // result on the heap.
             if statement.typ == StatementType::Assign {
             if statement.typ == StatementType::Assign {
                 let mut var = statement.lhs.clone().unwrap();
                 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];
                 var.typ = return_types[0];
                 stmt.lhs = Some(var.clone());
                 stmt.lhs = Some(var.clone());
                 heap.push(var.clone());
                 heap.push(var.clone());