#vulnerable code 
                                public Object execute(Object ctx, Map tokens) {
        if (nodes == null) {
            return new String(expression);
        }
        else if (nodes.length == 2) {
            switch (nodes[0].getToken()) {
                case PROPERTY_EX:
                    //noinspection unchecked
                    //  return ExpressionParser.eval(getInternalSegment(nodes[0]), ctx, tokens);

                    if (!cacheAggressively) {
                        char[] seg = new char[expression.length - 3];
                        arraycopy(expression, 2, seg, 0, seg.length);

                        return MVEL.eval(seg, ctx, tokens);
                    }
                    else {
                        String s = new String(expression, 2, expression.length - 3);
                        if (!EX_PRECOMP_CACHE.containsKey(s)) {
                            synchronized (EX_PRECOMP_CACHE) {
                                EX_PRECOMP_CACHE.put(s, MVEL.compileExpression(s));
                                return MVEL.executeExpression(EX_PRECOMP_CACHE.get(s), ctx, tokens);
                            }
                        }
                        else {
                            return MVEL.executeExpression(EX_PRECOMP_CACHE.get(s), ctx, tokens);
                        }

                    }
                case LITERAL:
                    return new String(expression);
                case INCLUDE_BY_REF: {
                    IncludeRef includeRef = (IncludeRef) nodes[0].getRegister();
                    String template = EX_TEMPLATE_REGISTRY.get( includeRef.getName() );
                    
                    IncludeRefParam[] params = includeRef.getParams();
                    Map vars = new HashMap( params.length );
                    for ( int i = 0; i < params.length; i++ ) {
                        vars.put( params[i].getIdentifier(), parse(params[i].getValue(), ctx, tokens));
                    }
                    
                    return Interpreter.parse( template, ctx, vars );                    
                }                    
            }

            return new String(expression);
        }

        Object register = null;

        StringAppender sbuf = new StringAppender(10);
        Node currNode = null;

        try {
            ExpressionParser oParser = new ExpressionParser(ctx, tokens);

            initStack();
            pushAndForward();

            while ((currNode = pop()) != null) {
                node = currNode.getNode();

                switch (currNode.getToken()) {
                    case LITERAL: {
                        sbuf.append(register = new String(expression, currNode.getStartPos(),
                                currNode.getEndPos() - currNode.getStartPos()));
                        break;
                    }
                    case PROPERTY_EX: {
                        sbuf.append(
                                valueOf(register = oParser.setExpressionArray(getInternalSegment(currNode)).parse())
                        );
                        break;
                    }
                    case IF:
                    case ELSEIF: {
                        try {
                            if (!((Boolean) oParser.setExpressionArray(getInternalSegment(currNode)).parse())) {
                                exitContext();
                            }
                        }
                        catch (ClassCastException e) {
                            throw new CompileException("IF expression does not return a boolean: " + new String(getSegment(currNode)));
                        }
                        break;
                    }
                    case FOREACH: {
                        ForeachContext foreachContext = ( ForeachContext ) currNode.getRegister();
                        if ( foreachContext.getItererators() == null ) {
                            try {
                                String[] lists = getForEachSegment(currNode).split( "," );
                                Iterator[] iters = new Iterator[lists.length];
                                for( int i = 0; i < lists.length; i++ ) {
                                    Object listObject = new ExpressionParser(lists[i], ctx, tokens).parse();
                                    if ( listObject instanceof Object[]) {
                                        listObject = Arrays.asList( (Object[]) listObject );
                                    }    
                                    iters[i] = ((Collection)listObject).iterator() ;
                                }
                                foreachContext.setIterators( iters );
                            } catch (ClassCastException e) {
                                throw new CompileException("expression for collections does not return a collections object: " + new String(getSegment(currNode)));
                            }
                            catch (NullPointerException e) {
                                throw new CompileException("null returned for foreach in expression: " + (getForEachSegment(currNode)));
                            }
                        }

                        Iterator[] iters = foreachContext.getItererators();
                        String[] alias = currNode.getAlias().split( "," );
                        // must trim vars
                        for ( int i = 0; i < alias.length; i++ ) {
                            alias[i] = alias[i].trim();
                        }                         
                        
                        if (iters[0].hasNext()) {
                            push();

                            //noinspection unchecked
                            for ( int i = 0; i < iters.length; i++ ) {
                                tokens.put(alias[i], iters[i].next());
                            }
                            if ( foreachContext.getCount() != 0 ) {
                                sbuf.append( foreachContext.getSeperator() );
                            }
                            foreachContext.setCount( foreachContext.getCount( ) + 1 );
                        }
                        else {
                            for ( int i = 0; i < iters.length; i++ ) {
                                tokens.remove(alias[i]);
                            }      
                            foreachContext.setIterators( null );
                            foreachContext.setCount( 0 );
                            exitContext();
                        }
                        break;
                    }
                    case ELSE:
                    case END:
                        if (stack.isEmpty()) forwardAndPush();
                        continue;
                    case GOTO:
                        pushNode(currNode.getEndNode());
                        continue;
                    case TERMINUS: {
                        if (nodes.length == 2) {
                            return register;
                        }
                        else {
                            return sbuf.toString();
                        }
                    }
                }

                forwardAndPush();
            }
            throw new CompileException("expression did not end properly: expected TERMINUS node");
        }
        catch (CompileException e) {
            throw e;
        }
        catch (Exception e) {
            if (currNode != null) {
                throw new CompileException("problem encountered at node [" + currNode.getNode() + "] "
                        + currNode.getToken() + "{" + currNode.getStartPos() + "," + currNode.getEndPos() + "}", e);
            }
            throw new CompileException("unhandled fatal exception (node:" + node + ")", e);
        }
    } 
                            #location 39 
                            #vulnerability type THREAD_SAFETY_VIOLATION
#fixed code
                                public Object execute(Object ctx, Map tokens) {
        if (nodes == null) {
            return new String(expression);
        }
        else if (nodes.length == 2) {
            /**
             * This is an optimization for property expressions.
             */
            switch (nodes[0].getToken()) {
                case PROPERTY_EX:
                    //noinspection unchecked
                    //  return ExpressionParser.eval(getInternalSegment(nodes[0]), ctx, tokens);

                    if (!cacheAggressively) {
                        char[] seg = new char[expression.length - 3];
                        arraycopy(expression, 2, seg, 0, seg.length);

                        return MVEL.eval(seg, ctx, tokens);
                    }
                    else {
                        String s = new String(expression, 2, expression.length - 3);
                        if (!EX_PRECOMP_CACHE.containsKey(s)) {
                            synchronized (EX_PRECOMP_CACHE) {
                                EX_PRECOMP_CACHE.put(s, MVEL.compileExpression(s));
                                return MVEL.executeExpression(EX_PRECOMP_CACHE.get(s), ctx, tokens);
                            }
                        }
                        else {
                            return MVEL.executeExpression(EX_PRECOMP_CACHE.get(s), ctx, tokens);
                        }

                    }
                case LITERAL:
                    return new String(expression);

            }

            return new String(expression);
        }

        Object register = null;

        StringAppender sbuf = new StringAppender(10);
        Node currNode = null;

        try {
            ExpressionParser oParser = new ExpressionParser(ctx, tokens);

            initStack();
            pushAndForward();

            while ((currNode = pop()) != null) {
                node = currNode.getNode();

                switch (currNode.getToken()) {
                    case LITERAL: {
                        sbuf.append(register = new String(expression, currNode.getStartPos(),
                                currNode.getEndPos() - currNode.getStartPos()));
                        break;
                    }
                    case PROPERTY_EX: {
                        sbuf.append(
                                valueOf(register = oParser.setExpressionArray(getInternalSegment(currNode)).parse())
                        );
                        break;
                    }
                    case IF:
                    case ELSEIF: {
                        try {
                            if (!((Boolean) oParser.setExpressionArray(getInternalSegment(currNode)).parse())) {
                                exitContext();
                            }
                        }
                        catch (ClassCastException e) {
                            throw new CompileException("IF expression does not return a boolean: " + new String(getSegment(currNode)));
                        }
                        break;
                    }
                    case FOREACH: {
                        ForeachContext foreachContext = (ForeachContext) currNode.getRegister();
                        if (foreachContext.getItererators() == null) {
                            try {
                                String[] lists = getForEachSegment(currNode).split(",");
                                Iterator[] iters = new Iterator[lists.length];
                                for (int i = 0; i < lists.length; i++) {
                                    Object listObject = new ExpressionParser(lists[i], ctx, tokens).parse();
                                    if (listObject instanceof Object[]) {
                                        listObject = Arrays.asList((Object[]) listObject);
                                    }
                                    iters[i] = ((Collection) listObject).iterator();
                                }
                                foreachContext.setIterators(iters);
                            }
                            catch (ClassCastException e) {
                                throw new CompileException("expression for collections does not return a collections object: " + new String(getSegment(currNode)));
                            }
                            catch (NullPointerException e) {
                                throw new CompileException("null returned for foreach in expression: " + (getForEachSegment(currNode)));
                            }
                        }

                        Iterator[] iters = foreachContext.getItererators();
                        String[] alias = currNode.getAlias().split(",");
                        // must trim vars
                        for (int i = 0; i < alias.length; i++) {
                            alias[i] = alias[i].trim();
                        }

                        if (iters[0].hasNext()) {
                            push();

                            //noinspection unchecked
                            for (int i = 0; i < iters.length; i++) {
                                tokens.put(alias[i], iters[i].next());
                            }
                            if (foreachContext.getCount() != 0) {
                                sbuf.append(foreachContext.getSeperator());
                            }
                            foreachContext.setCount(foreachContext.getCount() + 1);
                        }
                        else {
                            for (int i = 0; i < iters.length; i++) {
                                tokens.remove(alias[i]);
                            }
                            foreachContext.setIterators(null);
                            foreachContext.setCount(0);
                            exitContext();
                        }
                        break;
                    }
                    case ELSE:
                    case END:
                        if (stack.isEmpty()) forwardAndPush();
                        continue;
                    case GOTO:
                        pushNode(currNode.getEndNode());
                        continue;
                    case TERMINUS: {
                        if (nodes.length == 2) {
                            return register;
                        }
                        else {
                            return sbuf.toString();
                        }
                    }
                    case INCLUDE_BY_REF: {
                        IncludeRef includeRef = (IncludeRef) nodes[node].getRegister();
                        String template = EX_TEMPLATE_REGISTRY.get(includeRef.getName());

                        IncludeRefParam[] params = includeRef.getParams();
                        Map vars = new HashMap(params.length * 2);
                        for (int i = 0; i < params.length; i++) {
                            vars.put(params[i].getIdentifier(), MVEL.eval(params[i].getValue(), ctx, tokens));
                        }

                        sbuf.append(Interpreter.parse(template, ctx, vars));
                    }
                }

                forwardAndPush();
            }
            throw new CompileException("expression did not end properly: expected TERMINUS node");
        }
        catch (CompileException e) {
            throw e;
        }
        catch (Exception e) {
            if (currNode != null) {
                throw new CompileException("problem encountered at node [" + currNode.getNode() + "] "
                        + currNode.getToken() + "{" + currNode.getStartPos() + "," + currNode.getEndPos() + "}", e);
            }
            throw new CompileException("unhandled fatal exception (node:" + node + ")", e);
        }
    }