Commit Graph
22 Commits
Author SHA1 Message Date
std-odoo 3b97f601be [FIX] base: avoid variable name collision with functions in QWeb
Bug
===
The arguments of the lambda function might be the same as other
variables in the QWeb. In that case the template rendering will crash.

To avoid this issue, we encapsulate the name of the argument to be sure
it's not the same as other variable in the QWeb engine (so the name of
the argument can no longer make the QWeb rendering crash)

Task-2674716

Closes #78392.

Forward-port of 96b09b127028e5c9a83c89acce86e1b6df904c6f
2021-12-01 17:30:51 +01:00
Xavier Morel 8830525176 [ADD] core: 3.9 bytecode instructions in safe_eval
Python 3.9 has 10 new bytecode instructions, for now this commit adds 8

* CONTAINS_OP / IS_OP: moved out of COMPARE_OP which is now only used
  for *rich* comparisons (bpo-39156)
* JUMP_IF_NOT_EXC_MATCH: also moved out of COMPARE_OP for the sole
  purpose of testing exception types
* RERAISE and WITH_EXCEPT_START (bpo-32949) used to simplify the
  context manager bytecode, but RERAISE was then used for
  try/except/finally, we don't support context managers in safe_eval
  so we don't care about the latter
* LIST_TO_TUPLE, LIST_EXTEND, SET_UPDATE, DICT_MERGE and
  DICT_UPDATE (bpo-39320) updates to unpacking (* and **) in various
  contexts
  * LIST_TO_TUPLE we're skipping as it's only used when calling a
    function with two `*arg` parameters (aka `foo(*a, *b)`)
  * SET_UPDATE is used for set literals of 3 or more items or
    unpacking ({*a})
  * LIST_EXTEND is used in the same cases as well as function calls
    with unpacking
  * DICT_MERGE is used for function calls with `**kwargs`
  * DICT_UPDATE is used when unpacking in a dict literal (`{**kw}`)

See odoo/odoo#59980

closes odoo/odoo#62989

X-original-commit: 3d1c7231a080eebb4f6a7d56cbfa5721bf76befd
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2020-12-08 08:26:38 +00:00
Luis González 6430ca499f [FIX] tools/safe_eval: Add missing builtin sorted
Before this commit, the function `sorted` wasn't available on
`safe_eval`, even though it's a Python built-in, which mades it
unavailable for Python-code evaluation, e.g. server actions.

After this commit, the above function is now accessible.

closes odoo/odoo#59715

X-original-commit: a725c8927963848c3f8ada3b71897a54b740cce6
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2020-10-12 08:12:19 +00:00
Debauche StéphaneandXavier Morel 7ecb903bea [REM] *: ability to put raw modules in evaluation contexts
Co-authored-by: Xavier Morel <xmo@odoo.com>
2020-09-28 10:33:52 +02:00
Xavier Morel 0655974d5a [IMP] safe_eval: opcodes blacklist & cleanup
There are bytecode operations we don't support because we've never
needed them, and there are bytecode operations we don't support
because they're vectors of security issues.

Currently no difference is being made between the two, so when looking
to add a new opcodes it's hard to know whether it's been considered
and rejected or whether it just hasn't been considered (or found
useful) yet.

Add an explicit blacklist, which is explicitly subtracted to all
opcodes lists, to allow motivating the bans of certain
opcodes. Opcodes listed in no lists are the "graylists" of opcodes we
either haven't yet considered or have not had a use for.

Also cleanup the existing lists of opcodes to remove long-gone (or
even never-existing) opcodes, and add a few missing opcodes:

* DUP_TOPX was removed from Python 3, replaced by DUP_TOP_TWO
* STORE_MAP was removed in Python 3.5
* BINARY_DIVIDE and INPLACE_DIVIDE were removed from Python 3 (they
  were used to invoke P2's integer division)
* the SLICE+<X> were removed from Python 3, which only uses
  BUILD_SLICE
* CALL_FUNCTION_VAR and CALL_FUNCTION_VAR_KW were removed in Python
  3.6 and functionally replaced by CALL_FUNCTION_EX (bpo-27213)
* JUMP_IF_FALSE and JUMP_IF_TRUE were removed back in 2.7, replaced by
  POP_JUMP_* and JUMP_*_OR_POP (bpo-4715)
* various finally-related bytecode instructions were added to Python
  3.8 to improve and speed up the handling of return, break and
  continue (bpo-17611).
* INPLACE_REMAINDER, INPLACE_LEFTSHIFT and INPLACE_RIGHTSHIFT were
  mentioned in PEP 202 but never actually implemented: INPLACE_
  instructions were intended to mirror the BINARY_ instructions, these
  mnemonics didn't match the BINARY_ ones, so the actual mnemonics are
  INPLACE_MODULO, INPLACE_LSHIFT and INPLACE_RSHIFT
* while at it, BINARY_ and INPLACE_ mnemonics: as noted above they're
  mirrors of one another with different prefixes (except for SUBSCR
  which doesn't have an INPLACE version), we only supported a fraction
  of the INPLACE codes for unknown reason.

  Initially looked at simply aligning the BINARY and INPLACE mnemonics
  e.g.

       'BINARY_POWER',  'BINARY_MULTIPLY',  'BINARY_FLOOR_DIVIDE',
      'INPLACE_POWER', 'INPLACE_MULTIPLY', 'INPLACE_FLOOR_DIVIDE',
      ...

  so it would be easier to notice discrepancies, but it seems simpler
  and clearer to just move the suffixes to a single list and generate
  the BINARY_ and INPLACE_ mnemonics from that
* moved STORE_SUBSCR from EXPR to SAFE, I don't see how `foo[...] = 3`
  could be in an expression
* remove pseudo-graylist `_POSSIBLE_OPCODES_P3`, was intended as a
  list of new P3 opcodes we might want to add, but the purpose was
  hard to understand and a proper blacklist makes way more sense

closes odoo/odoo#41085

Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
2020-03-23 08:56:21 +00:00
Julien Castiaux ab4000fb3c [REF] base: Remove deprecated exceptions and osv
TL;DR: remember `osv` and `except_orm` ? You can forget about them.

* Deprecated `except_orm` dropped.
* `UserError` elevated as super type of all user-related
  errors.
* Unused `DeferredException` dropped.
* Unused `QWebException` dropped (real one is in `qweb.py`).
* `MailDeliveryException` made a python exception.
* `name` legacy exception attribute made an alias of the python standard
  `args[0]` attribute and deprecated.
* `value` legacy exception attribute dropped.
* `exception_type` RPC error response key dropped.
* Deprecated `osv` module dropped.
* `--osv-memory-age-limit` cli option made an alias of
  `--transient-age-limit` and deprecated.

The `odoo.exceptions.Warning` have long been a deprecated alias to
`UserError`. It is going to be removed in a future version but first we
explicitly deprecate it with a warning.

The `odoo.exceptions.DeferredException` was a very old internal
exception, it has been removed without deprecation notice as it is never
raised.

The `odoo.exceptions.except_orm` has been a deprecated exception type
with deprecation warning for 5 years, it has been removed in favor of
UserError which becomes the super class of all user-related errors.

The `odoo.base.models.ir_mail_server.MailDeliveryException` was
inheriting `except_orm`. As it is not related to a user error but is
more of a problem an admin much take care of, the exception has been
made a Python error.

The `exception_type` JSON key in RPC error responses was holding an
hardcoded value derived from the exception type. Its usage has been
dropped in favor of the `name` JSON key that holds the precise exception
name. Again as it was hardly used in the source code (beside the crash
manager) it has been dropped without deprecation warning.

Since we are here trying to clean odoo custom exceptions, we are also
deprecating the `name` exception attribute in favor of the more standard
`args[0]` attribute.

The `name` (along with `value`) were two attributes used to raise
`except_orm` exceptions before the introduction of `UserError`,
`AccessError` and related exceptions. The `name` attribute, at the time,
was holding the exception type/title. Nowadays it contains the error
message. The `value` attribute, at the time, was holding the error
message. Nowadays it is no more used.

The `osv` module contains very old deprecated aliases. There is no
simple way to log a deprecation warning for osv, osv_memory and
osv_abstract but as they have not been in use for ages, they have been
removed too. To be consistent, the `--osv-memory-age-limit` cli option
has been made a deprecated alias to the `--transient-age-limit`.

closes odoo/odoo#45723

Task: 2187728
Related: odoo/enterprise#9162
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-04-08 08:41:17 +00:00
Xavier Morel 6c4e4981bc [IMP] core: remove odoo.tools.safe_eval._get_opcodes
It's not necessary anymore as all supported Python versions implement
get_instructions, and inlining the usage of that is as readable as
calling _get_opcodes.

Also use the subset/superset predicate for validity testing instead of
difference as it's a fair bit faster:

    ❯ python3.8 -mtimeit -s 's1 = set(range(10)); s2 = set(range(5))' 's2 - s1'
    5000000 loops, best of 5: 88.3 nsec per loop
    ❯ python3.8 -mtimeit -s 's1 = set(range(10)); s2 = set(range(5, 15))' 's2 - s1'
    2000000 loops, best of 5: 159 nsec per loop
    ❯ python3.8 -mtimeit -s 's1 = set(range(10)); s2 = set(range(5))' 's1 >= s2'
    5000000 loops, best of 5: 71.1 nsec per loop
    ❯ python3.8 -mtimeit -s 's1 = set(range(10)); s2 = set(range(5, 15))' 's1 >= s2'
    5000000 loops, best of 5: 53.6 nsec per loop

we're paying double in the failure case but that doesn't super duper matter
because we're raising an exception and bailing out, the 24% gain on the
happy path seems more relevant.

closes odoo/odoo#48948

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2020-04-03 09:35:08 +00:00
Laurent Smet 5dc37da885 [IMP] tools: Don't shadow ZeroDivisionError with ValueError in safe_eval
If a division by zero occurs, I expect a ZeroDivisionError instead of a TypeError.
2020-01-03 13:00:03 +00:00
Xavier Morel badb95fbce [FIX] core: further pycompat cleanup
odoo/odoo#28519 removed large parts of pycompat, but left reraise
despite that not having much value.

Remove that helper and replace it by just a `raise` in most cases:
when raising from an except block, the old exception is automatically
chained to the new one, no need to mess around.

There is one exception: in http we have to re-raise an existing
exception explicitly (aka `raise exc` rather than just `raise).

This is less than ideal as Python *concatenates* stacks: the
previously reified stack (from the except clause) is stacked on top of
the new stack (from this raises), this leads to tracebacks "jumping
around" at the break point of the handler and is somewhat confusing.

So we want to use explicit chaining (`raise a from b`) with the
"source" providing the caught exception's original traceback and the
child providing the rest.

However since callers rely on the exception making sense, we need the
re-raised exception to be the original[0]. Copying the exception
doesn't work (see [0]), chaining an exception to itself doesn't
do anything useful, and while we could probably copy exceptions using
the pickle method[1] that's still risky.

So the most reliable option seems to be to create a new "cause"
exception, move the old traceback over to it, then re-raise the
original exception having cleared its traceback, chained to new the
cause.

[0] or a copy thereof but Odoo exceptions don't all work properly with
    copy.copy and we don't want that to fail so not really an option,
    we can't rely / bet on every new exception being cleanly copy-able
[1] create an "empty" instance using __new__ (or an instance of
    something else onto which we re-set the __class__ in case the exctype
    actually overrides __new__) then copy the __dict__

closes odoo/odoo#39709

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2019-11-05 08:14:10 +00:00
Adrian Torres 52f5528cfb [REF] *: replace deprecated pycompat helpers for builtins
This commit replaces calls to pycompat helpers that were intended for
python 2 <-> python 3 interoperability for python 3 builtins, as python
2 is no longer officially supported by Odoo.

This includes:
    * calls to imap/izip/ifilter replaced by map/zip/filter
    * uses of text_type replaced by str
    * uses of unichr replaced by chr
    * calls to implements_to_string, implements_iterator removed
    * string_types and integer_types replaced by str, int respectively
    * calls to to_native replaced by calls to to_text

This is done in preparation to the removal of these deprecated helpers
in the following commit.
2018-11-29 09:28:17 +00:00
Olivier Laurent 8ee329c1dc [FIX] P3: add missing opcode
In Python 3, SETUP_FINALLY is used if the exception object is bound in
the except block — even if there is no finally block — in order to
unbind and cleanup the exception's binding as part of PEP 3110:
https://www.python.org/dev/peps/pep-3110/#semantic-changes

This allows both using exception objects in Python 3 and using
finally blocks in both version.

opw 1824211
2018-07-30 09:49:59 +02:00
Martin Trigaux af9d6b86a1 [ADD] tools: add new 3.7 opcodes
Python 3.7 introduced two new opcodes LOAD_METHOD and CALL_METHOD.
https://docs.python.org/3/whatsnew/3.7.html#cpython-bytecode-changes
https://bugs.python.org/issue26110

Basic QWeb rendering was failing on operations like
      request.csrf_token()
ValueError: forbidden opcode(s) in 'request.csrf_token()': LOAD_METHOD, CALL_METHOD

Closes #25783
2018-07-17 13:42:50 +02:00
jaredkipe d7cfa8c502 [FIX]: safe_eval’ing some large scripts yield illegal opcodes
Following the 3.6 wordcode change, EXTENDED_ARGS gets used for jumps
offset by more than 256 bytes (128 opcodes), most commonly
absolute (so many script of more than 128 opcodes with conditionals
arer going to trigger the issue).

In bytecoded Python versions, EXTENDED_ARGS was only necessary above
65k opcodes: the opcode would get a separate 16-bits argument, while
wordcode opcodes get 8-bit intrinsic.
2017-10-17 16:16:42 +02:00
Xavier Morel 7dd062f835 [FIX] P3: text model types
* remove references to basestring & unicode (use relevant pycompat
  helpers)
* remove some str calls (either entirely or replaced by relevant
  helper, either text or native)
* use better API to avoid unnecessary conversions
* remove some XML declarations in views
2017-08-20 23:25:54 +02:00
Xavier Morel aaf8f3e37f [IMP] reorganise opcodes in categories 2017-06-26 16:45:03 +02:00
Xavier Morel 6e9d29df1d [FIX] P3: bytecode changes
* Python 3.4 adds new convenient bytecode-inspection API to dis which
  is nice, however Python 3.6 also switches from the old bytecode to a
  new wordcode which breaks _get_opcodes and *requires* that we use
  the new API
* add various opcodes which either were added in Python
  3 (CALL_FUNCTION_EX) or were only used for some small corners of
  Python 2 but have been expanded or despecialised in Python
  3 (BUILD_SLICE)
2017-06-26 16:45:02 +02:00
Xavier Morel 3dd3790597 [FIX] P3: raise exception with existing traceback
In Python 2, to raise a new exception but reuse a traceback requires a
special form of ``raise`` (``raise etype, evalue, tb``).

In Python 3, this is now done via a ``with_traceback`` method on
exception objects.

However this requires a bit of trickery as the former is invalid
syntax in Python 3, hence pycompat bridge created via an exec for
Python 2.
2017-05-12 16:15:39 +02:00
xmo-odoo fffaf735f5 [FIX] P3: list -> iterable builtins (#16811)
In Python 3:

* various builtins and dict methods were changed to return
  view/iterable objects rather than lists
* and the separate Python 2 view/iterable builtins and methods were
  removed altogether

This is problematic when using these items as list (which the happens
repeatedly in Odoo), but more viciously when iterating *multiple times*
over them (which also happens, which I've messed up multiple times while
writing this, and which is a pain to debug even when you've just created
the issue).

Convert all code using these to semantics-matching cross-version
helper functions to get the LCD behaviour between P2 and P3, and
forbid the builtins via lint.

issue #8530
2017-05-10 09:39:55 +02:00
xmo-odoo 2e6a589f41 [FIX] builtins removed from Python 3
* Reverse wrapper courtesy of @rco-odoo's original P3 branch
* thin compat module stripped down from werkzeug (to augment as needed)

issue 8530
2017-04-27 13:59:33 +02:00
Xavier Morel 3979f6802e [#8530] convert exception handlers to except..as syntax
Futurize fixers:
* lib2to3.fixes.fix_except
2017-04-11 14:53:29 +02:00
Raphael Collet 4a700d0ad9 [FIX] odoo: rename imports and adapt import hooks 2016-09-02 17:28:12 +02:00
Raphael Collet 9e64f9f951 [REF] openerp: move openerp to odoo 2016-09-02 17:28:12 +02:00