From 2ae11ec5085d6b2e9bd349ff37c123b9dd46b3e7 Mon Sep 17 00:00:00 2001 From: Vipul Bhatt Date: Wed, 10 Feb 2016 16:03:55 +0530 Subject: [PATCH] [IMP] base: 'ir.actions.server' 'code' field validation constraint - Only SAFE CODES (specified in openerp/tools/safe_eval.py) are allowed in server actions - Validating basic python errors eg. SyntaxError, IndentationError etc. --- openerp/addons/base/ir/ir_actions.py | 9 ++++++++- openerp/tools/safe_eval.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index ff3d0fbde45..20665102096 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -12,7 +12,7 @@ import odoo from odoo import api, fields, models, tools, workflow, _ from odoo.exceptions import MissingError, UserError, ValidationError from odoo.report.report_sxw import report_sxw, report_rml -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval as eval, test_python_expr _logger = logging.getLogger(__name__) @@ -596,6 +596,13 @@ class IrActionsServer(models.Model): model_name = field.comodel_name return (True, model_name, None) + @api.constrains('code') + def _check_python_code(self): + for action in self.filtered('code'): + msg = test_python_expr(expr=action.code.strip(), mode="exec") + if msg: + raise ValidationError(msg) + @api.constrains('write_expression', 'model_id') def _check_write_expression(self): for record in self: diff --git a/openerp/tools/safe_eval.py b/openerp/tools/safe_eval.py index a2f5e848c12..b140626c084 100644 --- a/openerp/tools/safe_eval.py +++ b/openerp/tools/safe_eval.py @@ -316,3 +316,20 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal import sys exc_info = sys.exc_info() raise ValueError, '"%s" while evaluating\n%r' % (ustr(e), expr), exc_info[2] +def test_python_expr(expr, mode="eval"): + try: + test_expr(expr, _SAFE_OPCODES, mode=mode) + except (SyntaxError, TypeError, ValueError) as err: + if len(err.args) >= 2 and len(err.args[1]) >= 4: + error = { + 'message': err.args[0], + 'filename': err.args[1][0], + 'lineno': err.args[1][1], + 'offset': err.args[1][2], + 'error_line': err.args[1][3], + } + msg = "%s : %s at line %d\n%s" % (type(err).__name__, error['message'], error['lineno'], error['error_line']) + else: + msg = ustr(err) + return msg + return False