From 1226f44ea2fa46953cab2aa278a1268499b6c4f6 Mon Sep 17 00:00:00 2001 From: michalkurka Date: Wed, 17 Mar 2021 12:51:23 -0400 Subject: [PATCH] Fix race condition in javassist javassist fails to find a class when concurrently running process compresses the class (converts classfile to raw bytes) the idea of the fix is to make sure to only update rawClassfile and classfile under lock in getClassFile3, all other places that modify classfile are already synchronized when reading the object state, we need to read under lock both classfile and rawClassFile otherwise we might get an inconsistent state --- .../src/main/java/javassist/CtClassType.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/h2o-core/src/main/java/javassist/CtClassType.java b/h2o-core/src/main/java/javassist/CtClassType.java index e4c95d6a89b4..5ea59ef3b9f6 100644 --- a/h2o-core/src/main/java/javassist/CtClassType.java +++ b/h2o-core/src/main/java/javassist/CtClassType.java @@ -179,6 +179,7 @@ public ClassFile getClassFile2() { } public ClassFile getClassFile3(boolean doCompress) { + // quick path - no locking ClassFile cfile = classfile; if (cfile != null) return cfile; @@ -186,17 +187,29 @@ public ClassFile getClassFile3(boolean doCompress) { if (doCompress) classPool.compress(); - if (rawClassfile != null) { + byte[] rcfile; + synchronized (this) { + // repeat under lock to make sure we get a consistent result (classfile might have been set by another thread) + cfile = classfile; + if (cfile != null) + return cfile; + + rcfile = rawClassfile; + } + + if (rcfile != null) { + final ClassFile cf; try { - ClassFile cf = new ClassFile(new DataInputStream( - new ByteArrayInputStream(rawClassfile))); - rawClassfile = null; - getCount = GET_THRESHOLD; - return setClassFile(cf); + cf = new ClassFile(new DataInputStream(new ByteArrayInputStream(rcfile))); } catch (IOException e) { throw new RuntimeException(e.toString(), e); } + getCount = GET_THRESHOLD; + synchronized (this) { + rawClassfile = null; + return setClassFile(cf); + } } InputStream fin = null;