Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unicode Decoding in String/Char Literal Evaluation #113

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 26 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .classpath
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
<classpathentry kind="lib" path="lib/bsf.jar"/>
<classpathentry kind="lib" path="lib/javacc.jar"/>
<classpathentry kind="lib" path="lib/servlet.jar"/>
<classpathentry kind="lib" path="lib/junit-4.4.jar"/>
<classpathentry kind="lib" path="lib/junit-4.8.2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## class files
classes/

## auto-generate code from javacc/jjtree
src/bsh/Parser.java
src/bsh/ParserConstants.java
src/bsh/ParserTokenManager.java
src/bsh/ParserTreeConstants.java
src/bsh/bsh.jj
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
This is the fork of [beanshell.org](http://www.beanshell.org/) called Beanshell2 which lived between 2011 and
2014 at [code.google.com](https://code.google.com/p/beanshell2). The motivation of the fork was that the
original author was no longer maintaining it.

In 2015 the repository moved here when Google retired their code hosting site.

The old version is again maintained at [github.com/beanshell](https://github.com/beanshell). There is some
ongoing effort to integrate the changes and improvements made to the project there.

The development branch here is [v2.1](https://github.com/pejobo/beanshell2/tree/v2.1), the latest 'released'
version is
[2.1.9](https://github.com/pejobo/beanshell2/raw/v2.1/dist/bsh-2.1.9.jar)
which maps to commit
[a70056fbe9727d8eadf8e21f3089cbe9f4f0913e](https://github.com/pejobo/beanshell2/commit/a70056fbe9727d8eadf8e21f3089cbe9f4f0913e).

See [releases page](https://github.com/pejobo/beanshell2/dist/README.md) for more information.


2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<property name="ant.build.javac.target" value="1.5" />
<property name="ant.build.javac.source" value="1.5" />
<property name="version" value="2.1b5"/>
<property name="version" value="2.2.0"/>
<property name="deprecation" value="on"/>
<property name="Specification-Title" value="BeanShell2" />
<property name="Specification-Version" value="${version}" />
Expand Down
63 changes: 63 additions & 0 deletions dist/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
March 13, 2018

* Update [2.1.9](https://github.com/pejobo/beanshell2/raw/v2.1/dist/bsh-2.1.9.jar)
* Drop of all remote code execution capabilities
* Restricting (de)serialization for security reasons (the serialization feature may be dropped in one of the next
releases) [#109](https://github.com/pejobo/beanshell2/issues/109)
* Ability to run with Java-9 and Java-10 with restricted module access (jvm flag _--illegal-access=deny_).
* Fixed a deadlock when pasting code into the graphical console
* [SHA512](https://raw.githubusercontent.com/pejobo/beanshell2/v2.1/dist/bsh-2.1.9.jar.sha512sum)

Feb. 20, 2014

* Update [2.1.8](https://github.com/pejobo/beanshell2/raw/5b925f056c7a4b192fcd7389c9362d4f43403f70/downloads/bsh-2.1.8.jar)
* fixes [#97](https://github.com/pejobo/beanshell2/issues/97),
[#98](https://github.com/pejobo/beanshell2/issues/98), and
[#99](https://github.com/pejobo/beanshell2/issues/99) - all variants of a regression introduced with
[#88](https://github.com/pejobo/beanshell2/issues/88)


Nov. 6, 2013

* Update 2.1.7
* Another hotfix when running beanshell in a security restricted environment
* Fix for finally block not executed when an exception is thrown in catch block - thanks to Lorenzo Cameroni for pointing this out and suggesting a fix


Sep. 27, 2013

* Update v2.1.6
* This release mainly fixes issues of running beanshell in a security restricted environment. This may break existing
scriptes which define classes with protected methods, constructors or fields or which access inherited protected
methods, constructors or fields. If your (script) code doesn't explicitly switch on the accessibility mode your
script code will break with this update.
To receive the old behaviour either call `bsh.Capabilities.setAccessibility(true)` in your java code or
`setAccessibility(true)` in your script code. This change was done to allow the usage of beanshell2 in security
restricted environments. See issue [#88](https://github.com/pejobo/beanshell2/issues/88) for code changes.
* New version number scheme (drop of b for build).


Nov. 21, 2011

* Update v2.1b5, fixing
* Do-while loop does not check condition on "continue" - issue [#57](https://github.com/pejobo/beanshell2/issues/57)
* Fixes when using JSR-223 an exception which is thrown for clause that shouldn't be evaluated - issue
[#60](https://github.com/pejobo/beanshell2/issues/60).

Older downloads are still available at [code.google.com](https://code.google.com/archive/p/beanshell2/downloads)

Other notable changes not mentioned above in contrast to the latest version available at
[beanshell.org](http://www.beanshell.org) are:
* The support for parsing of java files through the class loader has been dropped. It was considered more harmful than
helpful.
* The support of Java-5 varargs.
* Support for long string literals:
```
xml = """<books>
<book>
<title>Beanshell2</title>
</book>
</books>""""
```
* Build-in [jsr-233](https://www.jcp.org/en/jsr/detail?id=223) support (_Scripting for the Java Platform_).

7 changes: 0 additions & 7 deletions src/README.txt

This file was deleted.

29 changes: 29 additions & 0 deletions src/bsh/BSHLiteral.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,36 @@ private char getEscapeChar(char ch)
return ch;
}

public static String decode(String str) {
StringBuilder sb = new StringBuilder(str.length());
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (i + 1 < chars.length && c == '\\' && chars[i + 1] == 'u') {
char cc = 0;
for (int j = 0; j < 4; j++) {
char ch = Character.toLowerCase(chars[i + 2 + j]);
if ('0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F') {
cc |= (Character.digit(ch, 16) << (3 - j) * 4);
} else {
cc = 0;
break;
}
}
if (cc > 0) {
i += 5;
sb.append(cc);
continue;
}
}
sb.append(c);
}
return sb.toString();
}

public void charSetup(String str)
{
str = decode(str);
char ch = str.charAt(0);
if(ch == '\\')
{
Expand All @@ -104,6 +132,7 @@ public void charSetup(String str)

void stringSetup(String str)
{
str = decode(str);
StringBuilder buffer = new StringBuilder();
int len = str.length();
for(int i = 0; i < len; i++)
Expand Down
68 changes: 32 additions & 36 deletions src/bsh/BSHWhileStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,68 +31,64 @@
* *
*****************************************************************************/


package bsh;

/**
This class handles both while(){} statements and do{}while() statements.
* This class handles both {@code while} statements and {@code do..while} statements.
*/
class BSHWhileStatement extends SimpleNode implements ParserConstants
{
public boolean isDoStatement;
class BSHWhileStatement extends SimpleNode implements ParserConstants {

/**
* Set by Parser, default {@code false}
*/
boolean isDoStatement;

BSHWhileStatement(int id) { super(id); }
BSHWhileStatement(int id) {
super(id);
}

public Object eval( CallStack callstack, Interpreter interpreter)
throws EvalError
{

public Object eval( CallStack callstack, Interpreter interpreter) throws EvalError {
int numChild = jjtGetNumChildren();

// Order of body and condition is swapped for do / while
SimpleNode condExp, body = null;
final SimpleNode condExp;
final SimpleNode body;

if ( isDoStatement ) {
condExp = (SimpleNode)jjtGetChild(1);
body =(SimpleNode)jjtGetChild(0);
condExp = (SimpleNode) jjtGetChild(1);
body = (SimpleNode) jjtGetChild(0);
} else {
condExp = (SimpleNode)jjtGetChild(0);
if ( numChild > 1 ) // has body, else just for side effects
body =(SimpleNode)jjtGetChild(1);
condExp = (SimpleNode) jjtGetChild(0);
if ( numChild > 1 ) {
body = (SimpleNode) jjtGetChild(1);
} else {
body = null;
}
}

boolean doOnceFlag = isDoStatement;
while(
doOnceFlag ||
BSHIfStatement.evaluateCondition(condExp, callstack, interpreter )
)
{
if ( body == null ) // no body?
continue;

while (doOnceFlag || BSHIfStatement.evaluateCondition(condExp, callstack, interpreter)) {
doOnceFlag = false;
// no body?
if ( body == null ) {
continue;
}
Object ret = body.eval(callstack, interpreter);

boolean breakout = false;
if(ret instanceof ReturnControl)
{
switch(((ReturnControl)ret).kind )
{
if (ret instanceof ReturnControl) {
switch(( (ReturnControl)ret).kind ) {
case RETURN:
return ret;

case CONTINUE:
continue;
break;

case BREAK:
breakout = true;
break;
return Primitive.VOID;
}
}
if(breakout)
break;

doOnceFlag = false;
}

return Primitive.VOID;
}

Expand Down
28 changes: 28 additions & 0 deletions src/bsh/BshClassManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
Expand Down Expand Up @@ -185,8 +186,35 @@ public Class classForName( String name )
clas = plainClassForName( name );
} catch ( ClassNotFoundException e ) { /*ignore*/ }

// try scripted class
if ( clas == null && declaringInterpreter.getCompatibility() )
clas = loadSourceClass( name );

return clas;
}

// Move me to classpath/ClassManagerImpl???
protected Class<?> loadSourceClass( final String name ) {
final String fileName = '/' + name.replace('.', '/') + ".java";
final InputStream in = getResourceAsStream( fileName );
if ( in == null ) {
return null;
}
try {
Interpreter.debug("Loading class from source file: " + fileName);
declaringInterpreter.eval( new InputStreamReader(in) );
} catch ( EvalError e ) {
if (Interpreter.DEBUG) {
e.printStackTrace();
}
}
try {
return plainClassForName( name );
} catch ( final ClassNotFoundException e ) {
Interpreter.debug("Class not found in source file: " + name);
return null;
}
}

/**
Perform a plain Class.forName() or call the externally provided
Expand Down
6 changes: 3 additions & 3 deletions src/bsh/BshScriptEngineFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
public class BshScriptEngineFactory implements javax.script.ScriptEngineFactory {
// Begin impl ScriptEnginInfo

final List<String> extensions = Arrays.asList("bsh", "java");
final List<String> extensions = Arrays.asList("bsh");

final List<String> mimeTypes = Arrays.asList("application/x-beanshell", "application/x-bsh", "application/x-java-source");
final List<String> mimeTypes = Arrays.asList("application/x-beanshell", "application/x-bsh");

final List<String> names = Arrays.asList("beanshell", "bsh", "java");
final List<String> names = Arrays.asList("beanshell", "bsh");


public String getEngineName() {
Expand Down
8 changes: 8 additions & 0 deletions src/bsh/Capabilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

package bsh;

import java.lang.reflect.Field;
import java.util.Hashtable;

/**
Expand Down Expand Up @@ -80,6 +81,13 @@ public static void setAccessibility( boolean b )
// test basic access
try {
String.class.getDeclaredMethods();
try {
final Field field = Capabilities.class.getField("classes");
field.setAccessible(true);
field.setAccessible(false);
} catch (NoSuchFieldException e) {
// ignore
}
} catch ( SecurityException e ) {
throw new Unavailable("Accessibility unavailable: "+e);
}
Expand Down
2 changes: 1 addition & 1 deletion src/bsh/ClassGeneratorUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,7 @@ public static void initInstance(GeneratedClass instance, String className, Objec
if (e instanceof InvocationTargetException) {
e = (Exception) ((InvocationTargetException) e).getTargetException();
}
throw new InterpreterError("Error in class initialization: " + e);
throw new InterpreterError("Error in class initialization.", e);
}
}

Expand Down
Loading