diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-08-16 18:01:39 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-08-16 18:01:39 +0200 |
commit | ab8a223c6c01c1a725c9892c04952f6451aedf0d (patch) | |
tree | 37c7d98c711e47c9fd5670323c86b5f35fa8b1b5 /src | |
parent | 8053c197941608b06089de4a618615d46552aa0b (diff) | |
download | scala-ab8a223c6c01c1a725c9892c04952f6451aedf0d.tar.gz scala-ab8a223c6c01c1a725c9892c04952f6451aedf0d.tar.bz2 scala-ab8a223c6c01c1a725c9892c04952f6451aedf0d.zip |
SI-7603 Fix thread safety of FlagTranslation
This is outside of the Global cake, so we can't assume single
threaded access. A var was introduced in af3daf6fdb that can lead
to incorrect flag interpretation. The reported bug was triggered
in a multi-project SBT build. Java Annotations read from classfiles
were occasionally conferred the TRAIT|INFERFACE|ABSTRACT flag set,
leading to "@Foo is abstract, cannot be instatiated" later down the
line.
Diffstat (limited to 'src')
-rw-r--r-- | src/reflect/scala/reflect/internal/ClassfileConstants.scala | 36 |
1 files changed, 14 insertions, 22 deletions
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala index c198271fb1..eb70ff3f17 100644 --- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala +++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala @@ -335,13 +335,8 @@ object ClassfileConstants { abstract class FlagTranslation { import Flags._ - private var isAnnotation = false - private var isClass = false - private def initFields(flags: Int) = { - isAnnotation = (flags & JAVA_ACC_ANNOTATION) != 0 - isClass = false - } - private def translateFlag(jflag: Int): Long = (jflag: @switch) match { + private def isAnnotation(flags: Int): Boolean = (flags & JAVA_ACC_ANNOTATION) != 0 + private def translateFlag(jflag: Int, isAnnotation: Boolean, isClass: Boolean): Long = (jflag: @switch) match { case JAVA_ACC_PRIVATE => PRIVATE case JAVA_ACC_PROTECTED => PROTECTED case JAVA_ACC_FINAL => FINAL @@ -351,31 +346,28 @@ object ClassfileConstants { case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT case _ => 0L } - private def translateFlags(jflags: Int, baseFlags: Long): Long = { + private def translateFlags(jflags: Int, baseFlags: Long, isAnnotation: Boolean, isClass: Boolean): Long = { + def translateFlag0(jflags: Int): Long = translateFlag(jflags, isAnnotation, isClass) var res: Long = JAVA | baseFlags /** fast, elegant, maintainable, pick any two... */ - res |= translateFlag(jflags & JAVA_ACC_PRIVATE) - res |= translateFlag(jflags & JAVA_ACC_PROTECTED) - res |= translateFlag(jflags & JAVA_ACC_FINAL) - res |= translateFlag(jflags & JAVA_ACC_SYNTHETIC) - res |= translateFlag(jflags & JAVA_ACC_STATIC) - res |= translateFlag(jflags & JAVA_ACC_ABSTRACT) - res |= translateFlag(jflags & JAVA_ACC_INTERFACE) + res |= translateFlag0(jflags & JAVA_ACC_PRIVATE) + res |= translateFlag0(jflags & JAVA_ACC_PROTECTED) + res |= translateFlag0(jflags & JAVA_ACC_FINAL) + res |= translateFlag0(jflags & JAVA_ACC_SYNTHETIC) + res |= translateFlag0(jflags & JAVA_ACC_STATIC) + res |= translateFlag0(jflags & JAVA_ACC_ABSTRACT) + res |= translateFlag0(jflags & JAVA_ACC_INTERFACE) res } def classFlags(jflags: Int): Long = { - initFields(jflags) - isClass = true - translateFlags(jflags, 0) + translateFlags(jflags, 0, isAnnotation(jflags), isClass = true) } def fieldFlags(jflags: Int): Long = { - initFields(jflags) - translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0) + translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0 , isAnnotation(jflags), isClass = false) } def methodFlags(jflags: Int): Long = { - initFields(jflags) - translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE else 0) + translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE else 0, isAnnotation(jflags), isClass = false) } } object FlagTranslation extends FlagTranslation { } |