diff --git a/CHANGELOG.md b/CHANGELOG.md index d5c2342059..cc77232400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.5.4 (UNRELEASED) + +## Features: + +- [#352](http://github.com/Nelson-numerical-software/nelson/issues/352): number of input arguments checked in macro. + # 0.5.3 (2021-03-24) ## Features: @@ -18,7 +24,7 @@ - for loop faster > x2. -- assignment does not copy matrix. +- assignment does not copy matrix. - reworks ArrayOfVector (internal). diff --git a/modules/elementary_functions/functions/magic.nlf b/modules/elementary_functions/functions/magic.nlf index ce54ca1bcd..431c7b7943 100644 --- a/modules/elementary_functions/functions/magic.nlf +++ b/modules/elementary_functions/functions/magic.nlf @@ -24,7 +24,7 @@ // LICENCE_BLOCK_END //============================================================================= function M = magic(N) - if (nargin ~= 1) + if (nargin < 1) error(_('Wrong number of input arguments.')); end if (nargout > 1) diff --git a/modules/interpreter/src/cpp/MacroFunctionDef.cpp b/modules/interpreter/src/cpp/MacroFunctionDef.cpp index aae90fd126..4524b43ceb 100644 --- a/modules/interpreter/src/cpp/MacroFunctionDef.cpp +++ b/modules/interpreter/src/cpp/MacroFunctionDef.cpp @@ -170,22 +170,29 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, // argument function, then use the following logic: minCount = 0; if (inputArgCount() != -1) { + if (inputs.size() > arguments.size()) { + context->popScope(); + eval->callstack.popDebug(); + Error(ERROR_WRONG_NUMBERS_INPUT_ARGS); + } minCount = (inputs.size() < arguments.size()) ? inputs.size() : arguments.size(); for (size_t i = 0; i < minCount; i++) { std::string arg(arguments[i]); - if (arg[0] == '&') { - arg.erase(0, 1); - } context->insertVariableLocally(arg, inputs[i]); } - // context->insertVariableLocally("nargin", - // ArrayOf::doubleConstructor((double)minCount)); context->getCurrentScope()->setNargIn(static_cast(minCount)); } else { // Count the number of supplied arguments size_t inputCount = inputs.size(); - // context->insertVariableLocally("nargin", - // ArrayOf::doubleConstructor((double)inputCount)); + size_t nbArgumentsWithoutVarArgIn = arguments.size(); + if (arguments[arguments.size() - 1] == "varargin") { + nbArgumentsWithoutVarArgIn = nbArgumentsWithoutVarArgIn - 1; + } + if (inputCount < nbArgumentsWithoutVarArgIn) { + context->popScope(); + eval->callstack.popDebug(); + Error(ERROR_WRONG_NUMBERS_INPUT_ARGS); + } context->getCurrentScope()->setNargIn(static_cast(inputCount)); // Get the number of explicit arguments int explicitCount = static_cast(arguments.size()) - 1; @@ -197,9 +204,6 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, size_t i; for (i = 0; i < minCount; i++) { std::string arg(arguments[i]); - if (arg[0] == '&') { - arg.erase(0, 1); - } context->insertVariableLocally(arg, inputs[i]); } inputCount -= minCount; @@ -212,8 +216,6 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, } context->insertVariableLocally("varargin", varg); } - // context->insertVariableLocally("nargout", - // ArrayOf::doubleConstructor(nargout)); context->getCurrentScope()->setNargOut(nargout); uint64 tic = 0; try { @@ -251,6 +253,8 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, bool haveVarargout = context->lookupVariableLocally("varargout", varargout); if (haveVarargout) { if (varargout.getDataClass() != NLS_CELL_ARRAY) { + context->popScope(); + eval->callstack.popDebug(); Error(_W("The special variable 'varargout' was not defined as a " "cell-array.")); } @@ -259,6 +263,8 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, int explicitCount = static_cast(returnVals.size()) - 1; bool noArgs = (explicitCount == 0 && varlen == 0); if (!noArgs && !haveVarargout) { + context->popScope(); + eval->callstack.popDebug(); Error(_W("The special variable 'varargout' was not defined as expected.")); } if (explicitCount == 0 && varlen > 0 && nargout < 2) { @@ -268,6 +274,8 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, // Get the length if (static_cast(toFill) > static_cast(varargout.getElementCount())) { + context->popScope(); + eval->callstack.popDebug(); Error(_W("Not enough outputs in varargout to satisfy call.")); } outputs[0] = dp[0]; @@ -292,6 +300,8 @@ MacroFunctionDef::evaluateFunction(Evaluator* eval, const ArrayOfVector& inputs, // Get the length int toFill = nargout - explicitCount; if (static_cast(toFill) > static_cast(varlen)) { + context->popScope(); + eval->callstack.popDebug(); Error(_W("Not enough outputs in varargout to satisfy call.")); } for (int i = 0; i < toFill; i++) { diff --git a/modules/interpreter/tests/bug_github_issue_#352.nls b/modules/interpreter/tests/bug_github_issue_#352.nls new file mode 100644 index 0000000000..1b274a1917 --- /dev/null +++ b/modules/interpreter/tests/bug_github_issue_#352.nls @@ -0,0 +1,32 @@ +//============================================================================= +// Copyright (c) 2017 Allan CORNET (Nelson) +//============================================================================= +// This file is part of the Nelson. +//============================================================================= +// LICENCE_BLOCK_BEGIN +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program. If not, see . +// LICENCE_BLOCK_END +//============================================================================= +// <-- Issue URL --> +// https://github.com/Nelson-numerical-software/nelson/issues/352 +// <-- Short Description --> +// add nb input check on macros +//============================================================================= +assert_checkerror('magic(1, 1)', _('Wrong number of input arguments.')); +//=============================================================================