So you thought Java strings were immutable?

I was messing around with a bit of Java recently, and I just discovered that java.lang.String is in fact not 100% immutable

consider:


public class HelloWorld {

    public static void append(String s1, String s2) {
        try {
            Field value = String.class.getDeclaredField("value");
            value.setAccessible(true);
            value.set(s1, s2.toCharArray());
            Field count = String.class.getDeclaredField("count");
            count.setAccessible(true);
            count.set(s1, s2.length());
        } catch (Exception ex) {
        }
    }

    public static final String MESSAGE = "Hello world!";

    static {
        append(MESSAGE, "Lol goodbye");
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        System.out.println(MESSAGE);
    }

}


Yes, with reflection and similar tricks no class is immutable, keep in mind though that the hashcode is cached upon first calculating it. Iirc, String’s hashcode caching is removed in the more recent jdk7:s (that, or I dreamt it).

you can hack the hashCode as well by using reflection.

… or wreck havoc in otherwise mundane JEE applications where boxing/unboxing is common:

Integer instance = Integer.valueOf(63);
Field field = instance.getClass().getDeclaredField("value");
field.setAccessible(true);
field.set(instance, Integer.valueOf(62));


public int addOne(Integer value){
   return value + 1;
}

addOne(63) == 63;


public class Lol {

    static class Lololol extends Thread {

        public void run() {
            while (true) {
                rofl();
                try {
                    sleep(1000);
                } catch (Throwable t) {
                }
            }
        }

        public void rofl() {
            try {
                Field field = Integer.class.getDeclaredField("value");
                field.setAccessible(true);
                for (int i = -127; i <= 128; i++) {
                    field.setInt(
                            Integer.valueOf(i),
                            Math.random() < 0.5 ? -i : i);
                }
            } catch (Throwable t) {;
            }
        }

    }

    static void lol(Field field, Object newValue) throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Throwable {
        lol(Boolean.class.getField("FALSE"), true);
        boolean lol = Boolean.FALSE;
        System.out.println("lol: " + lol);
        new Lololol().start();

        Field field = Integer.class.getDeclaredField("value");
        field.setAccessible(true);
        field.setInt(Integer.valueOf(0), 1337);
        System.out.println((Integer) 0);

        for (;;) {
            Integer i1 = 1;
            Integer i2 = 2;

            System.out.println(i1 + i2);

            Thread.sleep(1000);
        }
    }

}


imagine putting this in some big application

remember this only works when the number is -127 to 128 though :wink:

This reminds me of http://thedailywtf.com/Articles/Disgruntled-Bomb-Java-Edition.aspx - not that anyone would do such a thing… eh-heh

heres one for .net:


typeof(string).GetField("Empty").SetValue(null, " ");

Yep taken from TDWTF

with C++ you can have even more fun:


#define if(X) if (float(rand())/float(RAND_MAX) > 0.01f && (X))
#ifdef TRUE
#undef TRUE
#endif
#ifdef FALSE
#undef FALSE
#endif
#define TRUE 0
#define FALSE 1

LOL, why is this possible :). Is there anyway to counter this?

I guess one could configure a security manager - or use an agent - that disables reflexive code. But that sounds like much less fun.

Don’t accept the code.

Oh, and in case anyone like messing with people in code, here’s a fun little webpage:

https://www.thc.org/root/phun/unmaintain.html