mirror of
https://github.com/github/codeql.git
synced 2026-05-03 12:45:27 +02:00
JPython code injection
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
public class JPythonInjection extends HttpServlet {
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
PythonInterpreter interpreter = null;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
interpreter = new PythonInterpreter();
|
||||
interpreter.setOut(out);
|
||||
interpreter.setErr(out);
|
||||
|
||||
// BAD: allow arbitrary JPython expression to execute
|
||||
interpreter.exec(code);
|
||||
out.flush();
|
||||
|
||||
response.getWriter().print(out.toString());
|
||||
} catch(PyException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
if (interpreter != null) {
|
||||
interpreter.close();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
PythonInterpreter interpreter = null;
|
||||
|
||||
try {
|
||||
interpreter = new PythonInterpreter();
|
||||
// BAD: allow arbitrary JPython expression to evaluate
|
||||
PyObject py = interpreter.eval(code);
|
||||
|
||||
response.getWriter().print(py.toString());
|
||||
} catch(PyException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
if (interpreter != null) {
|
||||
interpreter.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>Python has been the most widely used programming language in recent years, and JPython
|
||||
is a popular Java implementation of Python. It allows embedded Python scripting inside
|
||||
Java applications and provides an interactive interpreter that can be used to interact
|
||||
with Java packages or with running Java applications. If an expression is built using
|
||||
attacker-controlled data and then evaluated, it may allow the attacker to run arbitrary
|
||||
code.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>In general, including user input in JPython expression should be avoided. If user input
|
||||
must be included in an expression, it should be then evaluated in a safe context that
|
||||
doesn't allow arbitrary code invocation.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>The following code could execute random code in JPython Interpreter</p>
|
||||
<sample src="JPythonInjection.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
JPython Organization: <a href="https://jython.readthedocs.io/en/latest/JythonAndJavaIntegration/">JPython and Java Integration</a>
|
||||
</li>
|
||||
<li>
|
||||
PortSwigger: <a href="https://portswigger.net/kb/issues/00100f10_python-code-injection">Python code injection</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @name Injection in JPython
|
||||
* @description Evaluation of a user-controlled malicious expression in JPython
|
||||
* may lead to remote code execution.
|
||||
* @kind path-problem
|
||||
* @id java/jpython-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-094
|
||||
* external/cwe/cwe-095
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/** The class `org.python.util.PythonInterpreter`. */
|
||||
class PythonInterpreter extends RefType {
|
||||
PythonInterpreter() { this.hasQualifiedName("org.python.util", "PythonInterpreter") }
|
||||
}
|
||||
|
||||
/** A method that evaluates, compiles or executes a JPython expression. */
|
||||
class InterpretExprMethod extends Method {
|
||||
InterpretExprMethod() {
|
||||
this.getDeclaringType().getAnAncestor*() instanceof PythonInterpreter and
|
||||
(
|
||||
hasName("exec") or
|
||||
hasName("eval") or
|
||||
hasName("compile")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if a JPython expression if evaluated, compiled or executed. */
|
||||
predicate runCode(MethodAccess ma, Expr sink) {
|
||||
exists(Method m | m = ma.getMethod() |
|
||||
m instanceof InterpretExprMethod and
|
||||
sink = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
/** Sink of an expression interpreted by JPython interpreter. */
|
||||
class CodeInjectionSink extends DataFlow::ExprNode {
|
||||
CodeInjectionSink() { runCode(_, this.getExpr()) }
|
||||
|
||||
MethodAccess getMethodAccess() { runCode(result, this.getExpr()) }
|
||||
}
|
||||
|
||||
class CodeInjectionConfiguration extends TaintTracking::Configuration {
|
||||
CodeInjectionConfiguration() { this = "CodeInjectionConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source instanceof RemoteFlowSource
|
||||
or
|
||||
source instanceof LocalUserInput
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// @RequestBody MyQueryObj query; interpreter.exec(query.getInterpreterCode());
|
||||
exists(MethodAccess ma | ma.getQualifier() = node1.asExpr() and ma = node2.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, CodeInjectionConfiguration conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode().(CodeInjectionSink).getMethodAccess(), source, sink, "JPython evaluate $@.",
|
||||
source.getNode(), "user input"
|
||||
@@ -0,0 +1,11 @@
|
||||
edges
|
||||
| JPythonInjection.java:22:23:22:50 | getParameter(...) : String | JPythonInjection.java:30:28:30:31 | code |
|
||||
| JPythonInjection.java:47:21:47:48 | getParameter(...) : String | JPythonInjection.java:52:40:52:43 | code |
|
||||
nodes
|
||||
| JPythonInjection.java:22:23:22:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| JPythonInjection.java:30:28:30:31 | code | semmle.label | code |
|
||||
| JPythonInjection.java:47:21:47:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| JPythonInjection.java:52:40:52:43 | code | semmle.label | code |
|
||||
#select
|
||||
| JPythonInjection.java:30:11:30:32 | exec(...) | JPythonInjection.java:22:23:22:50 | getParameter(...) : String | JPythonInjection.java:30:28:30:31 | code | JPython evaluate $@. | JPythonInjection.java:22:23:22:50 | getParameter(...) | user input |
|
||||
| JPythonInjection.java:52:23:52:44 | eval(...) | JPythonInjection.java:47:21:47:48 | getParameter(...) : String | JPythonInjection.java:52:40:52:43 | code | JPython evaluate $@. | JPythonInjection.java:47:21:47:48 | getParameter(...) | user input |
|
||||
@@ -0,0 +1,64 @@
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.python.core.PyObject;
|
||||
import org.python.core.PyException;
|
||||
import org.python.util.PythonInterpreter;
|
||||
|
||||
public class JPythonInjection extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public JPythonInjection() {
|
||||
super();
|
||||
}
|
||||
|
||||
// BAD: allow arbitrary JPython expression to execute
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
PythonInterpreter interpreter = null;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
interpreter = new PythonInterpreter();
|
||||
interpreter.setOut(out);
|
||||
interpreter.setErr(out);
|
||||
interpreter.exec(code);
|
||||
out.flush();
|
||||
|
||||
response.getWriter().print(out.toString());
|
||||
} catch(PyException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
if (interpreter != null) {
|
||||
interpreter.close();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: allow arbitrary JPython expression to evaluate
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("text/plain");
|
||||
String code = request.getParameter("code");
|
||||
PythonInterpreter interpreter = null;
|
||||
|
||||
try {
|
||||
interpreter = new PythonInterpreter();
|
||||
PyObject py = interpreter.eval(code);
|
||||
|
||||
response.getWriter().print(py.toString());
|
||||
} catch(PyException ex) {
|
||||
response.getWriter().println(ex.getMessage());
|
||||
} finally {
|
||||
if (interpreter != null) {
|
||||
interpreter.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-094/JPythonInjection.ql
|
||||
@@ -1,2 +1,2 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jpython-2.7.2
|
||||
|
||||
|
||||
43
java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java
Normal file
43
java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Corporation for National Research Initiatives
|
||||
package org.python.core;
|
||||
|
||||
/**
|
||||
* A super class for all python code implementations.
|
||||
*/
|
||||
public abstract class PyCode extends PyObject
|
||||
{
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject args[], String keywords[],
|
||||
PyObject globals, PyObject[] defaults,
|
||||
PyObject closure);
|
||||
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject self, PyObject args[],
|
||||
String keywords[],
|
||||
PyObject globals, PyObject[] defaults,
|
||||
PyObject closure);
|
||||
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject globals, PyObject[] defaults,
|
||||
PyObject closure);
|
||||
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject arg1, PyObject globals,
|
||||
PyObject[] defaults, PyObject closure);
|
||||
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject arg1, PyObject arg2,
|
||||
PyObject globals, PyObject[] defaults,
|
||||
PyObject closure);
|
||||
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject arg1, PyObject arg2, PyObject arg3,
|
||||
PyObject globals, PyObject[] defaults,
|
||||
PyObject closure);
|
||||
|
||||
abstract public PyObject call(ThreadState state,
|
||||
PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4,
|
||||
PyObject globals, PyObject[] defaults,
|
||||
PyObject closure);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) Corporation for National Research Initiatives
|
||||
package org.python.core;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A wrapper for all python exception. Note that the well-known python exceptions are <b>not</b>
|
||||
* subclasses of PyException. Instead the python exception class is stored in the <code>type</code>
|
||||
* field and value or class instance is stored in the <code>value</code> field.
|
||||
*/
|
||||
public class PyException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) Corporation for National Research Initiatives
|
||||
package org.python.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* All objects known to the Jython runtime system are represented by an instance of the class
|
||||
* {@code PyObject} or one of its subclasses.
|
||||
*/
|
||||
public class PyObject implements Serializable {
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
// Copyright (c) Corporation for National Research Initiatives
|
||||
package org.python.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* The "sys" module.
|
||||
*/
|
||||
// xxx Many have lamented, this should really be a module!
|
||||
// but it will require some refactoring to see this wish come true.
|
||||
public class PySystemState extends PyObject {
|
||||
public PySystemState() {
|
||||
}
|
||||
|
||||
public static void classDictInit(PyObject dict) {
|
||||
}
|
||||
|
||||
public ClassLoader getSyspathJavaLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// xxx fix this accessors
|
||||
public PyObject __findattr_ex__(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void __setattr__(String name, PyObject value) {
|
||||
}
|
||||
|
||||
public void __delattr__(String name) {
|
||||
}
|
||||
|
||||
public PyObject gettrace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void settrace(PyObject tracefunc) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current working directory to the specified path.
|
||||
*
|
||||
* path is assumed to be absolute and canonical (via os.path.realpath).
|
||||
*
|
||||
* @param path a path String
|
||||
*/
|
||||
public void setCurrentWorkingDir(String path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representing the current working directory.
|
||||
*
|
||||
* @return a path String
|
||||
*/
|
||||
public String getCurrentWorkingDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a path. Returns the full path taking the current working directory into account.
|
||||
*
|
||||
* @param path a path String
|
||||
* @return a resolved path String
|
||||
*/
|
||||
public String getPath(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a path, returning a {@link File}, taking the current working directory into account.
|
||||
*
|
||||
* @param path a path <code>String</code>
|
||||
* @return a resolved <code>File</code>
|
||||
*/
|
||||
public File getFile(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
}
|
||||
|
||||
public static Properties getBaseProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static synchronized void initialize() {
|
||||
}
|
||||
|
||||
public static synchronized void initialize(Properties preProperties,
|
||||
Properties postProperties) {
|
||||
}
|
||||
|
||||
public static synchronized void initialize(Properties preProperties, Properties postProperties,
|
||||
String[] argv) {
|
||||
}
|
||||
|
||||
public static synchronized void initialize(Properties preProperties, Properties postProperties,
|
||||
String[] argv, ClassLoader classLoader) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a classpath directory to the list of places that are searched for java packages.
|
||||
* <p>
|
||||
* <b>Note</b>. Classes found in directory and sub-directory are not made available to jython by
|
||||
* this call. It only makes the java package found in the directory available. This call is
|
||||
* mostly useful if jython is embedded in an application that deals with its own class loaders.
|
||||
* A servlet container is a very good example. Calling
|
||||
* {@code add_classdir("<context>/WEB-INF/classes")} makes the java packages in WEB-INF classes
|
||||
* available to jython import. However the actual class loading is completely handled by the
|
||||
* servlet container's context classloader.
|
||||
*/
|
||||
public static void add_classdir(String directoryPath) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a .jar and .zip directory to the list of places that are searched for java .jar and .zip
|
||||
* files. The .jar and .zip files found will not be cached.
|
||||
* <p>
|
||||
* <b>Note</b>. Classes in .jar and .zip files found in the directory are not made available to
|
||||
* jython by this call. See the note for add_classdir(dir) for more details.
|
||||
*
|
||||
* @param directoryPath The name of a directory.
|
||||
*
|
||||
* @see #add_classdir
|
||||
*/
|
||||
public static void add_extdir(String directoryPath) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a .jar and .zip directory to the list of places that are searched for java .jar and .zip
|
||||
* files.
|
||||
* <p>
|
||||
* <b>Note</b>. Classes in .jar and .zip files found in the directory are not made available to
|
||||
* jython by this call. See the note for add_classdir(dir) for more details.
|
||||
*
|
||||
* @param directoryPath The name of a directory.
|
||||
* @param cache Controls if the packages in the zip and jar file should be cached.
|
||||
*
|
||||
* @see #add_classdir
|
||||
*/
|
||||
public static void add_extdir(String directoryPath, boolean cache) {
|
||||
}
|
||||
|
||||
// Not public by design. We can't rebind the displayhook if
|
||||
// a reflected function is inserted in the class dict.
|
||||
|
||||
/**
|
||||
* Exit a Python program with the given status.
|
||||
*
|
||||
* @param status the value to exit with
|
||||
* @throws PyException {@code SystemExit} always throws this exception. When caught at top level
|
||||
* the program will exit.
|
||||
*/
|
||||
public static void exit(PyObject status) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit a Python program with the status 0.
|
||||
*/
|
||||
public static void exit() {
|
||||
}
|
||||
|
||||
public static void exc_clear() {
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) Corporation for National Research Initiatives
|
||||
package org.python.core;
|
||||
|
||||
// a ThreadState refers to one PySystemState; this weak ref allows for tracking all ThreadState objects
|
||||
// that refer to a given PySystemState
|
||||
|
||||
public class ThreadState {
|
||||
|
||||
public PyException exception;
|
||||
|
||||
public ThreadState(PySystemState systemState) {
|
||||
setSystemState(systemState);
|
||||
}
|
||||
|
||||
public void setSystemState(PySystemState systemState) {
|
||||
}
|
||||
|
||||
public PySystemState getSystemState() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean enterRepr(PyObject obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void exitRepr(PyObject obj) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
package org.python.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.python.core.PyCode;
|
||||
import org.python.core.PyObject;
|
||||
|
||||
/**
|
||||
* The PythonInterpreter class is a standard wrapper for a Jython interpreter for embedding in a
|
||||
* Java application.
|
||||
*/
|
||||
public class PythonInterpreter implements Closeable {
|
||||
|
||||
/**
|
||||
* Initializes the Jython runtime. This should only be called once, before any other Python
|
||||
* objects (including PythonInterpreter) are created.
|
||||
*
|
||||
* @param preProperties A set of properties. Typically System.getProperties() is used.
|
||||
* preProperties override properties from the registry file.
|
||||
* @param postProperties Another set of properties. Values like python.home, python.path and all
|
||||
* other values from the registry files can be added to this property set.
|
||||
* postProperties override system properties and registry properties.
|
||||
* @param argv Command line arguments, assigned to sys.argv.
|
||||
*/
|
||||
public static void
|
||||
initialize(Properties preProperties, Properties postProperties, String[] argv) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new interpreter with an empty local namespace.
|
||||
*/
|
||||
public PythonInterpreter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new interpreter with the ability to maintain a separate local namespace for each
|
||||
* thread (set by invoking setLocals()).
|
||||
*
|
||||
* @param dict a Python mapping object (e.g., a dictionary) for use as the default namespace
|
||||
*/
|
||||
public static PythonInterpreter threadLocalStateInterpreter(PyObject dict) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new interpreter with a specified local namespace.
|
||||
*
|
||||
* @param dict a Python mapping object (e.g., a dictionary) for use as the namespace
|
||||
*/
|
||||
public PythonInterpreter(PyObject dict) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Python object to use for the standard output stream, <code>sys.stdout</code>. This
|
||||
* stream is used in a byte-oriented way (mostly) that depends on the type of file-like object.
|
||||
* The behaviour as implemented is:
|
||||
* <table border=1>
|
||||
* <caption>Stream behaviour for various object types</caption>
|
||||
* <tr align=center>
|
||||
* <td></td>
|
||||
* <td colspan=3>Python type of object <code>o</code> written</td>
|
||||
* </tr>
|
||||
* <tr align=left>
|
||||
* <th></th>
|
||||
* <th><code>str/bytes</code></th>
|
||||
* <th><code>unicode</code></th>
|
||||
* <th>Any other type</th>
|
||||
* </tr>
|
||||
* <tr align=left>
|
||||
* <th>{@link PyFile}</th>
|
||||
* <td>as bytes directly</td>
|
||||
* <td>respect {@link PyFile#encoding}</td>
|
||||
* <td>call <code>str(o)</code> first</td>
|
||||
* </tr>
|
||||
* <tr align=left>
|
||||
* <th>{@link PyFileWriter}</th>
|
||||
* <td>each byte value as a <code>char</code></td>
|
||||
* <td>write as Java <code>char</code>s</td>
|
||||
* <td>call <code>o.toString()</code> first</td>
|
||||
* </tr>
|
||||
* <tr align=left>
|
||||
* <th>Other {@link PyObject} <code>f</code></th>
|
||||
* <td>invoke <code>f.write(str(o))</code></td>
|
||||
* <td>invoke <code>f.write(o)</code></td>
|
||||
* <td>invoke <code>f.write(str(o))</code></td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* @param outStream Python file-like object to use as the output stream
|
||||
*/
|
||||
public void setOut(PyObject outStream) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link java.io.Writer} to use for the standard output stream, <code>sys.stdout</code>.
|
||||
* The behaviour as implemented is to output each object <code>o</code> by calling
|
||||
* <code>o.toString()</code> and writing this as UTF-16.
|
||||
*
|
||||
* @param outStream to use as the output stream
|
||||
*/
|
||||
public void setOut(java.io.Writer outStream) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link java.io.OutputStream} to use for the standard output stream.
|
||||
*
|
||||
* @param outStream OutputStream to use as output stream
|
||||
*/
|
||||
public void setOut(java.io.OutputStream outStream) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Python object to use for the standard output stream, <code>sys.stderr</code>. This
|
||||
* stream is used in a byte-oriented way (mostly) that depends on the type of file-like object,
|
||||
* in the same way as {@link #setOut(PyObject)}.
|
||||
*
|
||||
* @param outStream Python file-like object to use as the error output stream
|
||||
*/
|
||||
public void setErr(PyObject outStream) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link java.io.Writer} to use for the standard output stream, <code>sys.stdout</code>.
|
||||
* The behaviour as implemented is to output each object <code>o</code> by calling
|
||||
* <code>o.toString()</code> and writing this as UTF-16.
|
||||
*
|
||||
* @param outStream to use as the error output stream
|
||||
*/
|
||||
public void setErr(java.io.Writer outStream) {
|
||||
}
|
||||
|
||||
public void setErr(java.io.OutputStream outStream) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a string as a Python expression and returns the result.
|
||||
*/
|
||||
public PyObject eval(String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a Python code object and returns the result.
|
||||
*/
|
||||
public PyObject eval(PyObject code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a string of Python source in the local namespace.
|
||||
*
|
||||
* In some environments, such as Windows, Unicode characters in the script will be converted
|
||||
* into ascii question marks (?). This can be avoided by first compiling the fragment using
|
||||
* PythonInterpreter.compile(), and using the overridden form of this method which takes a
|
||||
* PyCode object. Code page declarations are not supported.
|
||||
*/
|
||||
public void exec(String s) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a Python code object in the local namespace.
|
||||
*/
|
||||
public void exec(PyObject code) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a file of Python source in the local namespace.
|
||||
*/
|
||||
public void execfile(String filename) {
|
||||
}
|
||||
|
||||
public void execfile(java.io.InputStream s) {
|
||||
}
|
||||
|
||||
public void execfile(java.io.InputStream s, String name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a string of Python source as either an expression (if possible) or a module.
|
||||
*
|
||||
* Designed for use by a JSR 223 implementation: "the Scripting API does not distinguish between
|
||||
* scripts which return values and those which do not, nor do they make the corresponding
|
||||
* distinction between evaluating or executing objects." (SCR.4.2.1)
|
||||
*/
|
||||
public PyCode compile(String script) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PyCode compile(Reader reader) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PyCode compile(String script, String filename) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PyCode compile(Reader reader, String filename) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a variable in the local namespace.
|
||||
*
|
||||
* @param name the name of the variable
|
||||
* @param value the object to set the variable to (as converted to an appropriate Python object)
|
||||
*/
|
||||
public void set(String name, Object value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a variable in the local namespace.
|
||||
*
|
||||
* @param name the name of the variable
|
||||
* @param value the Python object to set the variable to
|
||||
*/
|
||||
public void set(String name, PyObject value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a variable in the local namespace.
|
||||
*
|
||||
* @param name the name of the variable
|
||||
* @return the value of the variable, or null if that name isn't assigned
|
||||
*/
|
||||
public PyObject get(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a variable in the local namespace.
|
||||
*
|
||||
* The value will be returned as an instance of the given Java class.
|
||||
* <code>interp.get("foo", Object.class)</code> will return the most appropriate generic Java
|
||||
* object.
|
||||
*
|
||||
* @param name the name of the variable
|
||||
* @param javaclass the class of object to return
|
||||
* @return the value of the variable as the given class, or null if that name isn't assigned
|
||||
*/
|
||||
public <T> T get(String name, Class<T> javaclass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user