Slicer4J icon indicating copy to clipboard operation
Slicer4J copied to clipboard

Slicer4J doesn't include declaration of variable, on which variable from slice is data-dependent.

Open ArtemUntila opened this issue 4 years ago • 4 comments

Issue.java:

1.  public class Issue {
2.  
3.      public static void main(String[] args) {
4.          int b = 2;
5.          int a = 1 + b;
6.          System.out.println(a);
7.      }
8.  }

Running Slicer4J w.r.t. Issue:6 line:

cd scripts
python3 slicer4j.py -j .../issue.jar -o .../issue -b Issue:6 -m "Issue"

slice.log:

Issue:5
Issue:6

Despite variable a is data-dependent on variable b, the line with declaration of variable b wasn't included in slice.log.

In the example from README the same situation is observed:

For the example, slice.log contains:

SliceMe:4
SliceMe:7
SliceMe:9

Which indicates that the slice is:

4.        if (args.length > 0){
7.            parsed = null;
9.        System.out.println(parsed.length);

In this example line with declaration of variable parsed also wasn't included in slice.log.

Is such behaviour expected?

ArtemUntila avatar Aug 06 '21 12:08 ArtemUntila

For the Issue class:

4.          int b = 2;
5.          int a = 1 + b;

If you look at the raw slice, you'll notice that line 5 becomes int a = 3. This is due to constant propagation done by soot when creating the instrumented JAR. So it conceals the dependency of 5 on 4 as b does not appear in line 5 anymore. If b is not constant, it will be in the slice. Currently, I have no way of disabling the constant propagation in soot.

As for the readme example:

4.        if (args.length > 0){
7.            parsed = null;
9.        System.out.println(parsed.length);

the re-assignment of parsed at line 7 overwrites any value of parsed before line 7. So line 7 is not data-dependent on the definition of parsed. This is the expected behaviour.

khaled-e-a avatar Aug 06 '21 15:08 khaled-e-a

Hi! @khaled-e-a Thank you for providing this tool. I was trying this tool on Defects4j, but I found a similar problem that confused me as follows. The bug id is Lang 11 and the buggy function is:

public static String random(int count, int start, int end, boolean letters, boolean numbers,
                                char[] chars, Random random) {
        if (count == 0) {
            return "";
        } else if (count < 0) {
            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
        }
        if (chars != null && chars.length == 0) {
            throw new IllegalArgumentException("The chars array must not be empty");
        }

        if (start == 0 && end == 0) {
            if (chars != null) {
                end = chars.length;
            } else {
                if (!letters && !numbers) {
                    end = Integer.MAX_VALUE;
                } else {
                    end = 'z' + 1;
                    start = ' ';                
                }
            }
        }

        char[] buffer = new char[count];
        int gap = end - start;

        while (count-- != 0) {
            char ch;
            if (chars == null) {
                ch = (char) (random.nextInt(gap) + start); // line 253
            } else {
                ch = chars[random.nextInt(gap) + start];
            }
            if (letters && Character.isLetter(ch)
                    || numbers && Character.isDigit(ch)
                    || !letters && !numbers) {
                if(ch >= 56320 && ch <= 57343) {
                    if(count == 0) {
                        count++;
                    } else {
                        // low surrogate, insert high surrogate after putting it in
                        buffer[count] = ch;
                        count--;
                        buffer[count] = (char) (55296 + random.nextInt(128));
                    }
                } else if(ch >= 55296 && ch <= 56191) {
                    if(count == 0) {
                        count++;
                    } else {
                        // high surrogate, insert low surrogate before putting it in
                        buffer[count] = (char) (56320 + random.nextInt(128));
                        count--;
                        buffer[count] = ch;
                    }
                } else if(ch >= 56192 && ch <= 56319) {
                    // private high surrogate, no effing clue, so skip it
                    count++;
                } else {
                    buffer[count] = ch;
                }
            } else {
                count++;
            }
        }
        return new String(buffer);
    }

the value of arguments are : count: 3, start: 5 end: 5, letters: false, numbers: false,chars=null, the function throwed an exception under these input because the random.nextInt(gap)function had input 0. I want to slicing at line 253 : ch = (char) (random.nextInt(gap) + start); // line 253 this is the slice.log the tool generated:

org.apache.commons.lang3.RandomStringUtils:69
org.apache.commons.lang3.RandomStringUtils:143
org.apache.commons.lang3.RandomStringUtils:163
org.apache.commons.lang3.RandomStringUtils:252
org.apache.commons.lang3.RandomStringUtils:253

it only include line 252, line 253 in this function:

if (chars == null) {
                ch = (char) (random.nextInt(gap) + start); // line 253

As you can see, there are two variable in line 253 gap and start, why the slices did not include those lines like int gap = end - start;? Was those the expected slices? I am confused by the slicing criteria. Hope you can give me some help. Sincerely thanks.

Aric3 avatar Apr 03 '25 08:04 Aric3

Hi @Aric3

Can you please provide a zip file that I can use to replicate your execution scenario? i.e., please provide me the compiled jar under test, a script to run the Jar with those specific inputs and runs Slicer4J with the command line arguments (and slice criterion) you provided?

Thank you!

khaled-e-a avatar May 10 '25 00:05 khaled-e-a

Hi @khaled-e-a I am so excited to see your reply! I put my code in the attachment, slicer.py is a script to run Slicer4j by python command, for example, python3 slicer.py Lang_11b You can put slicer.py and Lang_11b(after extract) under folder benchmark , and then run command above to get the slices, which will be like this:

org.apache.commons.lang3.RandomStringUtils:69
org.apache.commons.lang3.RandomStringUtils:143
org.apache.commons.lang3.RandomStringUtils:163
org.apache.commons.lang3.RandomStringUtils:252
org.apache.commons.lang3.RandomStringUtils:253

Example.zip

Aric3 avatar May 12 '25 08:05 Aric3