You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gentoo-overlay/dev-java/jython/files/CVE-2016-4000.patch

159 lines
6.3 KiB

# HG changeset patch
# User Jim Baker <jim.baker@rackspace.com>
# Date 1454384221 25200
# Node ID d06e29d100c04576735e86c75a26c5f33669bb72
# Parent b6735606c13df95f770527e629954407f82808c5
Do not deserialize PyFunction objects. Fixes #2454
Instead use standard Python pickling; or subclass PyFunction.
diff --git a/Lib/test/test_java_integration.py b/Lib/test/test_java_integration.py
--- a/Lib/test/test_java_integration.py
+++ b/Lib/test/test_java_integration.py
@@ -14,8 +14,9 @@ import re
from collections import deque
from test import test_support
-from java.lang import (ClassCastException, ExceptionInInitializerError, String, Runnable, System,
- Runtime, Math, Byte)
+from java.lang import (
+ ClassCastException, ExceptionInInitializerError, UnsupportedOperationException,
+ String, Runnable, System, Runtime, Math, Byte)
from java.math import BigDecimal, BigInteger
from java.net import URI
from java.io import (ByteArrayInputStream, ByteArrayOutputStream, File, FileInputStream,
@@ -656,13 +657,30 @@ class SerializationTest(unittest.TestCas
self.assertEqual(date_list, roundtrip_serialization(date_list))
def test_java_serialization_pycode(self):
-
def universal_answer():
return 42
serialized_code = roundtrip_serialization(universal_answer.func_code)
self.assertEqual(eval(serialized_code), universal_answer())
+ def test_java_serialization_pyfunction(self):
+ # Not directly supported due to lack of general utility
+ # (globals will usually be in the function object in
+ # func_globals), and problems with unserialization
+ # vulnerabilities. Users can always subclass from PyFunction
+ # for specific cases, as seen in PyCascading
+ import new
+ def f():
+ return 6 * 7 + max(0, 1, 2)
+ # However, using the new module, it's possible to create a
+ # function with no globals, which means the globals will come
+ # from the current context
+ g = new.function(f.func_code, {}, "g")
+ # But still forbid Java deserialization of this function
+ # object. Use pickling or other support instead.
+ with self.assertRaises(UnsupportedOperationException):
+ roundtrip_serialization(g)
+
def test_builtin_names(self):
import __builtin__
names = [x for x in dir(__builtin__)]
@@ -872,7 +890,7 @@ class SingleMethodInterfaceTest(unittest
future.get()
self.assertEqual(x, [42])
- @unittest.skip("FIXME: not working")
+ @unittest.skip("FIXME: not working; see http://bugs.jython.org/issue2115")
def test_callable_object(self):
callable_obj = CallableObject()
future = self.executor.submit(callable_obj)
diff --git a/Lib/test/test_new.py b/Lib/test/test_new.py
--- a/Lib/test/test_new.py
+++ b/Lib/test/test_new.py
@@ -24,18 +24,10 @@ class NewTest(unittest.TestCase):
c = new.instance(C, {'yolks': 3})
o = new.instance(C)
-
- # __dict__ is a non dict mapping in Jython
- if test_support.is_jython:
- self.assertEqual(len(o.__dict__), 0, "new __dict__ should be empty")
- else:
- self.assertEqual(o.__dict__, {}, "new __dict__ should be empty")
+ self.assertEqual(o.__dict__, {}, "new __dict__ should be empty")
del o
o = new.instance(C, None)
- if test_support.is_jython:
- self.assertEqual(len(o.__dict__), 0, "new __dict__ should be empty")
- else:
- self.assertEqual(o.__dict__, {}, "new __dict__ should be empty")
+ self.assertEqual(o.__dict__, {}, "new __dict__ should be empty")
del o
def break_yolks(self):
@@ -109,7 +101,14 @@ class NewTest(unittest.TestCase):
test_closure(g, (1, 1), ValueError) # closure is wrong size
test_closure(f, g.func_closure, ValueError) # no closure needed
- if hasattr(new, 'code') and not test_support.is_jython:
+ # [Obsolete] Note: Jython will never have new.code()
+ #
+ # Who said that?!!! guess what, we do! :)
+ #
+ # Unfortunately we still need a way to compile to Python bytecode,
+ # so support is still incomplete, as seen in the fact that we need
+ # to get values from CPython 2.7.
+ if hasattr(new, 'code'):
def test_code(self):
# bogus test of new.code()
def f(a): pass
@@ -117,16 +116,16 @@ class NewTest(unittest.TestCase):
c = f.func_code
argcount = c.co_argcount
nlocals = c.co_nlocals
- stacksize = c.co_stacksize
+ stacksize = 1 # TODO c.co_stacksize
flags = c.co_flags
- codestring = c.co_code
- constants = c.co_consts
- names = c.co_names
+ codestring = 'd\x00\x00S' # TODO c.co_code
+ constants = (None,) # TODO c.co_consts
+ names = () # TODO c.co_names
varnames = c.co_varnames
filename = c.co_filename
name = c.co_name
firstlineno = c.co_firstlineno
- lnotab = c.co_lnotab
+ lnotab = '' # TODO c.co_lnotab, but also see http://bugs.jython.org/issue1638
freevars = c.co_freevars
cellvars = c.co_cellvars
diff --git a/src/org/python/core/PyBytecode.java b/src/org/python/core/PyBytecode.java
--- a/src/org/python/core/PyBytecode.java
+++ b/src/org/python/core/PyBytecode.java
@@ -66,6 +66,12 @@ public class PyBytecode extends PyBaseCo
debug = defaultDebug;
+ if (argcount < 0) {
+ throw Py.ValueError("code: argcount must not be negative");
+ } else if (nlocals < 0) {
+ throw Py.ValueError("code: nlocals must not be negative");
+ }
+
co_argcount = nargs = argcount;
co_varnames = varnames;
co_nlocals = nlocals; // maybe assert = varnames.length;
diff --git a/src/org/python/core/PyFunction.java b/src/org/python/core/PyFunction.java
--- a/src/org/python/core/PyFunction.java
+++ b/src/org/python/core/PyFunction.java
@@ -545,6 +545,9 @@ public class PyFunction extends PyObject
@Override
public boolean isSequenceType() { return false; }
+ private Object readResolve() {
+ throw new UnsupportedOperationException();
+ }
/* Traverseproc implementation */
@Override