[Soot-list] Jasmin annotation bug(fix)

Christophe Foket christophe.foket at elis.ugent.be
Fri Dec 2 09:01:30 EST 2011


Hi Eric,

There still seems to be an issue with the fix I posted before. The fact 
is that it will not work in case you have array annotations that 
actually have a name.

jasmin calls setNoName() at two different locations, both in 
jasmin.ClassFile:

    380          if (methAnnotDef != null){
    381              methAnnotDef.setNoName();
    382              currentMethod.addAnnotationDef(new 
AnnotationDefaultAttr(methAnnotDef));
    383          }

and

   1031      ElemValPair makeArrayElem(String name, char kind, Object list){
   1032          ArrayElemValPair elem = new ArrayElemValPair(name, 
kind, (ArrayList)list);
   1033          elem.setNoName();
   1034          return elem;
   1035      }

I confirmed that blindly calling setNoName() on an ArrayElemValPair can 
also result in corrupt bytecode if the annotation actually has a name. 
The easiest way to fix this would be to rewrite setNoName() in 
ArrayElemValPair once again to:

     public void setNoName(){
         if(name.uniq.equals("default")) // check if the annotation has 
no name
             super.setNoName();
         if (list == null) return;
         Iterator it = list.iterator();
         while (it.hasNext()){
             ((ElemValPair)it.next()).setNoName();
         }
     }

As a result, the name of the annotation will be omitted if it is not 
set. Note that the name "default" is used to signify that the annotation 
has no name. This is done in soot.coffi.Util when the class file is read 
during the initialization of soot. The createElementTags method, used to 
handle annotations, contains the following code:

    987      String elemName = "default";
    988      if (ev.name_index != 0){
    989          elemName = 
((CONSTANT_Utf8_info)coffiClass.constant_pool[ev.name_index]).convert();
    990      }

Annotations with no name have an ev.name_index of 0, and hence their 
name is set to "default".

I know that checking whether the name equals "default" is kind of hacky. 
Unfortunately, this is the only thing I could come up with for now, 
given my limited knowledge of jasmin.

Best,

Christophe

On 12/01/2011 05:52 PM, Eric Bodden wrote:
> Hello Christophe.
>
> Thanks a lot for this fix! I have just committed it.
>
> Your help is greatly appreciated.
>
> Best wishes,
> Eric
>
> On 30 November 2011 20:36, Christophe Foket
> <christophe.foket at elis.ugent.be>  wrote:
>> Hello,
>>
>> I am trying to run Soot on the tradebeans benchmark, which is part of the
>> latest dacapo release. For this, I am using the methodology described here:
>> http://www.bodden.de/2010/03/29/soot-tamiflex-dacapo/. One of the dumped
>> classes is "javax.persistence.OneToMany". This class is read in correctly by
>> soot, but written out incorrectly even if no transformations are applied to
>> it.
>>
>> The problem with this class is that there are two extra bytes inserted in
>> the annotation of one of its methods. Below is the output of "javap -verbose
>> javax.persistence.OneToMany" for both the original class and the
>> (untransformed) class generated by soot.
>>
>> Original:
>> =====
>>
>> public abstract javax.persistence.CascadeType[] cascade();
>>      Signature:
>> ()[Ljavax/persistence/CascadeType;
>>      AnnotationDefault: length =
>> 0x3
>>       5B 00
>> 00
>>
>> Sootified:
>> ======
>>
>> public abstract javax.persistence.CascadeType[]
>> cascade();
>>      Signature: ()[Ljavax/persistence/CascadeType;
>>      AnnotationDefault: length = 0x5
>>      00 17 5B 00 00
>>
>> Note that the 5B 00 00, corresponds to an array (5B is '[') of size zero,
>> which is what we expect. The "00 17", on the other hand points to an entry
>> in the constant pool, representing the name of the array annotation, which
>> is "default". After some debugging, I found out that the annotation is
>> internally represented by an ArrayElemValPair. ArrayElemValPair extends
>> ElemValPair, which defines a method setNoName() that, when called makes sure
>> that the constant pool index of the ElemValPair's name is not written out.
>> The problem, however, is in ArrayElemValPair, which overrides setNoName(),
>> without performing a super call:
>>
>>      public void setNoName(){
>>          if (list == null) return;
>>          Iterator it = list.iterator();
>>          while (it.hasNext()){
>>              ((ElemValPair)it.next()).setNoName();
>>          }
>>      }
>>
>> In this case, the setNoName() method is called on all elements of the list,
>> but not on the annotation itself. Therefore, whenever the annotation is
>> written out, it ithe constant pool index of its name is also written out.
>> Changing the implementation of setNoName() to
>>
>>      public void setNoName(){
>>          super.setNoName();
>>          if (list == null) return;
>>          Iterator it = list.iterator();
>>          while (it.hasNext()){
>>              ((ElemValPair)it.next()).setNoName();
>>          }
>>      }
>>
>> causes Soot to generate the class file correctly.
>>
>> I don't know enough about the internals of jasmin to decide whether or not
>> this fixes the issue entirely, but it at least seemed to solve my problem.
>>
>> Best,
>>
>> Christophe
>>
>> _______________________________________________
>> Soot-list mailing list
>> Soot-list at sable.mcgill.ca
>> http://mailman.cs.mcgill.ca/mailman/listinfo/soot-list
>>
>
>



More information about the Soot-list mailing list