2

My java source code was gone so i need to edit the .class directly. Here's the specific method body from whole .class file that i need to modify, decompiled view by JD GUI :

  public static BigDecimal countKilosonName(TicketInfo paramTicketInfo)
  {
    int i = 0;
    BigDecimal localBigDecimal = new BigDecimal(0);
    while (i < paramTicketInfo.getLinesCount())
    {
      String str1 = paramTicketInfo.getLine(i).getProductName();
      int j = (int)paramTicketInfo.getLine(i).getMultiply();
      Pattern localPattern = Pattern.compile("\\([+-]?([0-9]*[.])?[0-9]+ (kg|KG|Kg|kG)\\)");
      Matcher localMatcher = localPattern.matcher(str1);
      String str2 = "";
      if (localMatcher.find())
      {
        str2 = localMatcher.group();
        String str3 = str2.replaceAll(" (?i)kg", "").replaceAll("\\(", "").replaceAll("\\)", "");
        double d = j * Double.parseDouble(str3);
        localBigDecimal = localBigDecimal.add(BigDecimal.valueOf(d));
        paramTicketInfo.getLine(i).setProperty("product.name.altered", paramTicketInfo.getLine(i).getProductName().replace("(" + str3 + " kg)", "(" + d + " kg)"));
      }
      i++;
    }
    return localBigDecimal;
  }

Here's the starting bytecode editor :

iconst_0
istore_1
new java/math/BigDecimal
dup
iconst_0
invokespecial java/math/BigDecimal/<init>(I)V
astore_2
iload_1
aload_0
invokevirtual com/openbravo/pos/ticket/TicketInfo/getLinesCount()I
if_icmpge 92
aload_0
iload_1
invokevirtual com/openbravo/pos/ticket/TicketInfo/getLine(I)Lcom/openbravo/pos/ticket/TicketLineInfo;
invokevirtual com/openbravo/pos/ticket/TicketLineInfo/getProductName()Ljava/lang/String;
astore_3
aload_0
iload_1
invokevirtual com/openbravo/pos/ticket/TicketInfo/getLine(I)Lcom/openbravo/pos/ticket/TicketLineInfo;
invokevirtual com/openbravo/pos/ticket/TicketLineInfo/getMultiply()D
d2i
istore 4
ldc_w "\([+-]?([0-9]*[.])?[0-9]+ (kg|KG|Kg|kG)\)"
invokestatic java/util/regex/Pattern/compile(Ljava/lang/String;)Ljava/util/regex/Pattern;
astore 5
aload 5
aload_3
invokevirtual java/util/regex/Pattern/matcher(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;
astore 6
ldc ""
astore 7
aload 6
invokevirtual java/util/regex/Matcher/find()Z
ifeq 90
aload 6
invokevirtual java/util/regex/Matcher/group()Ljava/lang/String;
astore 7
aload 7
ldc_w " (?i)kg"
ldc ""
invokevirtual java/lang/String/replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
ldc_w "\("
ldc ""
invokevirtual java/lang/String/replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
ldc_w "\)"
ldc ""
invokevirtual java/lang/String/replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
astore 8
iload 4
i2d
aload 8
invokestatic java/lang/Double/parseDouble(Ljava/lang/String;)D
dmul
dstore 9
aload_2
dload 9
invokestatic java/math/BigDecimal/valueOf(D)Ljava/math/BigDecimal;
invokevirtual java/math/BigDecimal/add(Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
astore_2
aload_0
iload_1
invokevirtual com/openbravo/pos/ticket/TicketInfo/getLine(I)Lcom/openbravo/pos/ticket/TicketLineInfo;
ldc_w "product.name.altered"
aload_0
iload_1
invokevirtual com/openbravo/pos/ticket/TicketInfo/getLine(I)Lcom/openbravo/pos/ticket/TicketLineInfo;
invokevirtual com/openbravo/pos/ticket/TicketLineInfo/getProductName()Ljava/lang/String;
new java/lang/StringBuilder
dup
invokespecial java/lang/StringBuilder/<init>()V
ldc_w "("
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
aload 8
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
ldc_w " kg)"
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
new java/lang/StringBuilder
dup
invokespecial java/lang/StringBuilder/<init>()V
ldc_w "("
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
dload 9
invokevirtual java/lang/StringBuilder/append(D)Ljava/lang/StringBuilder;
ldc_w " kg)"
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
invokevirtual java/lang/String/replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
invokevirtual com/openbravo/pos/ticket/TicketLineInfo/setProperty(Ljava/lang/String;Ljava/lang/String;)V
iinc 1 1
goto 8
aload_2
areturn

On line 84 i replace :

invokevirtual java/lang/StringBuilder/append(D)Ljava/lang/StringBuilder;

with

invokestatic java/math/BigDecimal/valueOf(D)Ljava/math/BigDecimal;
invokevirtual java/lang/StringBuilder/append(Ljava/math/BigDecimal;)Ljava/lang/StringBuilder;

My purpose is to change the source code :

... .setProperty("product.name.altered", paramTicketInfo.getLine(i).getProductName().replace("(" + str3 + " kg)", "(" + d + " kg)"));

to

... .setProperty("product.name.altered", paramTicketInfo.getLine(i).getProductName().replace("(" + str3 + " kg)", "(" + BigDecimal.valueOf(d) + " kg)"));

because i got a known long decimal problem using double, so i need to change it to BigDecimal.

But when i click the Save method button on the Java Bytecode Editor, something is not right then when i open the .class again using JD GUI, the line while (i < paramTicketInfo.getLinesCount()) is gone and replaced with only for (;;). Although the line change from d to BigDecimal.valueOf(d) was looking good. Sorry if most likely i'm missing a basic .class bytecode knowledge. My plan if the bytecode editing is success i will generate the new class using ASM to recompute the stackmaptable, then using 7-zip i will attach it back to the .jar file. Many thanks.

wai-eiy
  • 21
  • 1
  • Could you please post the (binary) classfiles before and after your changes? – Antimony Feb 21 '19 at 05:30
  • 1
    is the byte code for the while construct different to the one for the for? see e.g. https://stackoverflow.com/questions/23775476/asm-bytecode-to-identify-for-while-loops – kai Feb 21 '19 at 07:58
  • @Antimony here's the whole .class file before and after edit : https://wetransfer.com/downloads/52c98843eb9987bf8efd2bb360f9147820190221093228/731e09 – wai-eiy Feb 21 '19 at 09:36
  • 1
    There is no `append(BigDecimal)` method in `StringBuilder`, so you would have to use `java/lang/StringBuilder/append(Ljava/lang/Object;)Ljava/lang/StringBuilder;` instead. Besides that, there’s only a semantic problem, as it doesn’t help the issue you want to fix, to inject `BigDecimal` *after* you have a `double`. You likely want to replace `double d = j * Double.parseDouble(str3); localBigDecimal = localBigDecimal.add(BigDecimal.valueOf(d));` with `BigDecimal d = new BigDecimal(str3).multiply​(BigDecimal.valueOf(j)); localBigDecimal = localBigDecimal.add(d);` – Holger Feb 21 '19 at 12:27

0 Answers0