Skip to content

java.lang.IllegalStateException: Object method calls can not be decomposed #3592

@luisggpina

Description

@luisggpina

Input for SIMPLE_OPTIMIZATIONS:

throw (a_0 <= (a_0 => null)[(() => 762)(++ a_0)]())

Error output:

java.lang.IllegalStateException: Object method calls can not be decomposed.
	at com.google.common.base.Preconditions.checkState(Preconditions.java:508)
	at com.google.javascript.jscomp.ExpressionDecomposer.exposeExpression(ExpressionDecomposer.java:218)
	at com.google.javascript.jscomp.ExpressionDecomposer.exposeExpression(ExpressionDecomposer.java:136)
	at com.google.javascript.jscomp.ExpressionDecomposer.maybeExposeExpression(ExpressionDecomposer.java:110)
	at com.google.javascript.jscomp.FunctionInjector$CallSiteType$6.prepare(FunctionInjector.java:520)
	at com.google.javascript.jscomp.FunctionInjector.maybePrepareCall(FunctionInjector.java:593)
	at com.google.javascript.jscomp.InlineFunctions.decomposeExpressions(InlineFunctions.java:794)
	at com.google.javascript.jscomp.InlineFunctions.process(InlineFunctions.java:152)
	at com.google.javascript.jscomp.PhaseOptimizer$NamedPass.process(PhaseOptimizer.java:317)
	at com.google.javascript.jscomp.PhaseOptimizer$Loop.process(PhaseOptimizer.java:462)
	at com.google.javascript.jscomp.PhaseOptimizer.process(PhaseOptimizer.java:232)
	at com.google.javascript.jscomp.Compiler.performOptimizations(Compiler.java:2417)
	at com.google.javascript.jscomp.Compiler.lambda$stage2Passes$1(Compiler.java:802)
	at com.google.javascript.jscomp.CompilerExecutor.runInCompilerThread(CompilerExecutor.java:129)
	at com.google.javascript.jscomp.Compiler.runInCompilerThread(Compiler.java:829)
	at com.google.javascript.jscomp.Compiler.stage2Passes(Compiler.java:799)
	at com.google.javascript.jscomp.Compiler.compileModules(Compiler.java:744)
	at com.google.javascript.jscomp.debugger.CompilationServlet.service(CompilationServlet.java:99)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1772)
	at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:582)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
	at com.google.apphosting.runtime.jetty9.ParseBlobUploadHandler.handle(ParseBlobUploadHandler.java:119)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1182)
	at com.google.apphosting.runtime.jetty9.AppEngineWebAppContext.doHandle(AppEngineWebAppContext.java:187)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at com.google.apphosting.runtime.jetty9.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:293)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
	at org.eclipse.jetty.server.Server.handle(Server.java:539)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:333)
	at com.google.apphosting.runtime.jetty9.RpcConnection.handle(RpcConnection.java:213)
	at com.google.apphosting.runtime.jetty9.RpcConnector.serviceRequest(RpcConnector.java:81)
	at com.google.apphosting.runtime.jetty9.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:134)
	at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchServletRequest(JavaRuntime.java:757)
	at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchRequest(JavaRuntime.java:720)
	at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:690)
	at com.google.apphosting.runtime.JavaRuntime$NullSandboxRequestRunnable.run(JavaRuntime.java:882)
	at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:270)
	at java.lang.Thread.run(Thread.java:748)

Reproduce URL: https://closure-compiler-debugger.appspot.com/#input0%3Dthrow%2520(a_0%2520%253C%253D%2520(a_0%2520%253D%253E%2520null)%255B(()%2520%253D%253E%2520762)(%252B%252B%2520a_0)%255D())%250A%26input1%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3Dtrue%26ALIAS_ALL_STRINGS%3Dtrue%26AMBIGUATE_PROPERTIES%3Dtrue%26COALESCE_VARIABLE_NAMES%3Dtrue%26COLLAPSE_VARIABLE_DECLARATIONS%3Dtrue%26COLLAPSE_ANONYMOUS_FUNCTIONS%3Dtrue%26COLLAPSE_PROPERTIES%3Dtrue%26COLLAPSE_OBJECT_LITERALS%3Dtrue%26COMPUTE_FUNCTION_SIDE_EFFECTS%3Dtrue%26CONVERT_TO_DOTTED_PROPERTIES%3Dtrue%26CROSS_CHUNK_CODE_MOTION%3Dtrue%26CROSS_CHUNK_METHOD_MOTION%3Dtrue%26DEAD_ASSIGNMENT_ELIMINATION%3Dtrue%26DISAMBIGUATE_PROPERTIES%3Dtrue%26EXTRACT_PROTOTYPE_MEMBER_DECLARATIONS%3Dtrue%26FOLD_CONSTANTS%3Dtrue%26INLINE_CONSTANTS%3Dtrue%26INLINE_FUNCTIONS%3Dtrue%26INLINE_PROPERTIES%3Dtrue%26INLINE_VARIABLES%3Dtrue%26LABEL_RENAMING%3Dtrue%26OPTIMIZE_CALLS%3Dtrue%26REMOVE_ABSTRACT_METHODS%3Dtrue%26REMOVE_DEAD_CODE%3Dtrue%26REMOVE_UNUSED_CLASS_PROPERTIES%3Dtrue%26REMOVE_UNUSED_PROTOTYPE_PROPERTIES%3Dtrue%26REMOVE_UNUSED_PROTOTYPE_PROPERTIES_IN_EXTERNS%3Dtrue%26REMOVE_UNUSED_VARIABLES%3Dtrue%26REWRITE_FUNCTION_EXPRESSIONS%3Dtrue%26SMART_NAME_REMOVAL%3Dtrue%26USE_TYPES_FOR_LOCAL_OPTIMIZATION%3Dtrue%26VARIABLE_RENAMING%3Dtrue%26PROPERTY_RENAMING%3Dtrue%26MOVE_FUNCTION_DECLARATIONS%3Dtrue%26SYNTHETIC_BLOCK_MARKER%3Dtrue%26CHROME_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue

This error can also be reproduced with the following input:

() => (a_0(this[(() => (762))(++ a_0)]()))

Passed to the following class:

import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.Result;
import com.google.javascript.jscomp.SourceFile;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import static org.junit.Assume.assumeTrue;

public class Compiler {

    static {
        java.util.logging.LogManager.getLogManager().reset();
    }

    // Compiler, options, and predefined JS environment
    private com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler(new PrintStream(new ByteArrayOutputStream(), false));
    private CompilerOptions options = new CompilerOptions();
    private SourceFile externs = SourceFile.fromCode("externs", "");

    public void initCompiler() {
        // Don't use threads
        compiler.disableThreads();
        // Don't print things
        options.setPrintConfig(false);
        // Enable all safe optimizations
        CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
    }

    /** Compiles an input and returns its result */
    private Result compile(SourceFile input) {
        return compiler.compile(externs, input, options);
    }

    public static void main(String[] args) {
        Compiler t = new Compiler();
        t.compiler = new com.google.javascript.jscomp.Compiler(System.out);
        t.initCompiler();
        t.compiler.compile(t.externs, SourceFile.fromFile(args[0]), t.options);
    }
}

Compiler Options (default options)

aggressiveFusion=false
 aliasableStrings=[]
 aliasAllStrings=false
 aliasHandler=com.google.javascript.jscomp.CompilerOptions$NullAliasTransformationHandler@5bb21b69
 aliasStringsBlacklist=
 allowHotswapReplaceScript=false
 ambiguateProperties=false
 angularPass=false
 anonymousFunctionNaming=OFF
 assumeClosuresOnlyCaptureReferences=false
 assumeGettersArePure=true
 assumeStrictThis=false
 browserResolverPrefixReplacements={}
 brokenClosureRequiresLevel=ERROR
 checkDeterminism=false
 checkGlobalNamesLevel=OFF
 checkGlobalThisLevel=OFF
 checkMissingGetCssNameLevel=OFF
 checksOnly=false
 checkSuspiciousCode=false
 checkSymbols=false
 checkTypes=false
 closurePass=true
 coalesceVariableNames=true
 collapseAnonymousFunctions=false
 collapseObjectLiterals=true
 collapseProperties=NONE
 collapseVariableDeclarations=true
 colorizeErrorOutput=false
 computeFunctionSideEffects=false
 conformanceConfigs=[]
 conformanceRemoveRegexFromPath=Optional.of(^((.*/)?google3/)?((^/)?(blaze|bazel)-out/[^/]+/bin/)?)
 continueAfterErrors=false
 convertToDottedProperties=true
 crossChunkCodeMotion=false
 crossChunkCodeMotionNoStubMethods=false
 crossChunkMethodMotion=false
 dartPass=false
 deadAssignmentElimination=true
 declaredGlobalExternsOnWindow=true
 defineReplacements={}
 dependencyOptions=DependencyOptions{mode=SORT_ONLY
 entryPoints=[]}
 devirtualizeMethods=false
 devMode=OFF
 disambiguatePrivateProperties=false
 disambiguateProperties=false
 enableModuleRewriting=true
 enforceAccessControlCodingConventions=false
 environment=BROWSER
 errorFormat=SINGLELINE
 es6ModuleTranspilation=COMPILE
 exportLocalPropertyDefinitions=false
 exportTestFunctions=false
 externExports=false
 extractPrototypeMemberDeclarations=OFF
 extraSmartNameRemoval=false
 filesToPrintAfterEachPassRegexList=[]
 flowSensitiveInlineVariables=false
 foldConstants=true
 forceLibraryInjection=[]
 gatherCssNames=false
 generateExports=false
 generatePseudoNames=false
 generateTypedExterns=false
 idGenerators={}
 incrementalCheckMode=OFF
 inferConsts=true
 inferTypes=false
 inlineConstantVars=false
 inlineFunctionsLevel=LOCAL_ONLY
 inlineGetters=false
 inlineLocalVariables=true
 inlineProperties=false
 inlineVariables=false
 inputDelimiter=// Input %num%
 inputSourceMaps={}
 instrumentForCoverage=false
 instrumentForCoverageOnly=false
 instrumentBranchCoverage=false
 isolatePolyfills=false
 j2clMinifierEnabled=true
 j2clPassMode=AUTO
 labelRenaming=true
 languageIn=ECMASCRIPT_2019
 languageOutIsDefaultStrict=Optional.absent()
 legacyCodeCompile=false
 lineBreak=false
 lineLengthThreshold=500
 markAsCompiled=false
 maxFunctionSizeAfterInlining=-1
 moduleRoots=[./]
 chunksToPrintAfterEachPassRegexList=[]
 moveFunctionDeclarations=false
 nameGenerator=com.google.javascript.jscomp.DefaultNameGenerator@32464a14
 optimizeArgumentsArray=true
 optimizeCalls=false
 outputFeatureSet=Optional.absent()
 outputJs=NORMAL
 outputJsStringUsage=false
 parentChunkCanSeeSymbolsDeclaredInChildren=false
 parseJsDocDocumentation=TYPES_ONLY
 pathEscaper=ESCAPE
 polymerExportPolicy=LEGACY
 preferLineBreakAtEndOfFile=false
 preferSingleQuotes=false
 preferStableNames=false
 preserveDetailedSourceInfo=false
 preserveGoogProvidesAndRequires=false
 preserveTypeAnnotations=false
 prettyPrint=false
 preventLibraryInjection=false
 printConfig=true
 printInputDelimiter=false
 printSourceAfterEachPass=false
 processCommonJSModules=false
 propertyInvalidationErrors={}
 propertyRenaming=OFF
 protectHiddenSideEffects=true
 quoteKeywordProperties=false
 removeAbstractMethods=false
 removeClosureAsserts=false
 removeJ2clAsserts=true
 removeDeadCode=true
 removeUnusedClassProperties=false
 removeUnusedConstructorProperties=false
 removeUnusedLocalVars=true
 removeUnusedPrototypeProperties=false
 removeUnusedPrototypePropertiesInExterns=false
 removeUnusedVars=false
 renamePrefixNamespaceAssumeCrossChunkNames=false
 replaceIdGenerators=false
 replaceMessagesWithChromeI18n=false
 replaceStringsFunctionDescriptions=[]
 replaceStringsPlaceholderToken=
 replaceStringsReservedStrings=[]
 reserveRawExports=false
 rewriteFunctionExpressions=false
 rewritePolyfills=false
 runtimeTypeCheck=false
 shadowVariables=true
 rewriteModulesBeforeTypechecking=true
 skipNonTranspilationPasses=false
 smartNameRemoval=false
 sourceMapDetailLevel=ALL
 sourceMapFormat=DEFAULT
 sourceMapLocationMappings=[]
 stripNamePrefixes=[]
 stripNameSuffixes=[]
 stripTypePrefixes=[]
 stripTypes=[]
 summaryDetailLevel=1
 tracer=OFF
 transformAMDToCJSModules=false
 trustedStrings=false
 tweakProcessing=OFF
 tweakReplacements={}
 emitUseStrict=Optional.absent()
 useTypesForLocalOptimization=false
 variableRenaming=LOCAL
 warningsGuard=DiagnosticGroup<checkVars>(OFF)
 DiagnosticGroup<es5Strict>(ERROR)
 DiagnosticGroup<boundedGenerics>(OFF)
 com.google.javascript.jscomp.DiagnosticGroup@4e4aea35(OFF)
 wrapGoogModulesForWhitespaceOnly=true

Affects: v20200405

Activity

rrdelaney

rrdelaney commented on May 11, 2020

@rrdelaney
Contributor

What is your use-case here? I don't think this JS would ever be run in a browser.

luisggpina

luisggpina commented on May 12, 2020

@luisggpina
Author

We found this crashing input using a fuzzing tool that generates inputs automatically which may result in a crash. In this case, our tool found such an input: A piece of JavaScript that results in the compiler crashing with a IllegalStateException.

Our tool only generates valid JavaScript (as per the JavaScript grammar), so this is a bug as the compiler should reject the input instead of crashing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P4bugtriage-doneHas been reviewed by someone on triage rotation.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @brad4d@rrdelaney@luisggpina

      Issue actions

        java.lang.IllegalStateException: Object method calls can not be decomposed · Issue #3592 · google/closure-compiler