Anuken/Arc

Incorrect requests expansion in SortedSpriteBatch

Qendolin opened this issue · 0 comments

There is a major issue in this piece of code

float[] requestZ = this.requestZ;
if(numRequests + count - offset >= this.requests.length) expandRequests();
DrawRequest[] requests = this.requests;

Sometimes the game crashes with an ArrayIndexOutOfBoundsException on line 72.
This happens because requestZ is assigned before the call to expandRequests so it will still use the old array

Here is an example:

float[] requestZ = this.requestZ; // local requestZ => Array[30625]

// expandRequests is called and reassigns this.requestZ
this.requestZ = Arrays.copyOf(requestZ, newRequests.length); // field requestZ => Array[53593]

// after expandRequests
requestZ == this.requestZ; // False! because requestZ still references Array[30625]

Here is a stack trace of the issue, a debugger statement tells me that requests was just expanded from 30625 to 53593:

[E] java.lang.ArrayIndexOutOfBoundsException: Index 30625 out of bounds for length 30625
	at arc.graphics.g2d.SortedSpriteBatch.draw(SortedSpriteBatch.java:72)
	at arc.graphics.g2d.Draw.vert(Draw.java:371)
	at arc.graphics.g2d.FontCache.draw(FontCache.java:234)
	at arc.graphics.g2d.Font.draw(Font.java:235)
	at mindustry.gen.Player.draw(Player.java:645)
	at mindustry.entities.EntityGroup.draw(EntityGroup.java:104)
	at mindustry.core.Renderer.draw(Renderer.java:370)
	at mindustry.core.Renderer.update(Renderer.java:224)
	at arc.ApplicationCore.update(ApplicationCore.java:37)
	at mindustry.ClientLauncher.update(ClientLauncher.java:230)
	at arc.backend.sdl.SdlApplication.listen(SdlApplication.java:204)
	at arc.backend.sdl.SdlApplication.loop(SdlApplication.java:192)
	at arc.backend.sdl.SdlApplication.<init>(SdlApplication.java:54)
	at mindustry.desktop.DesktopLauncher.main(DesktopLauncher.java:39)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at com.qendolin.mindustryloader.gameprovider.services.MindustryGameProvider.launch(MindustryGameProvider.java:200)
	at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:77)
	at net.fabricmc.loader.launch.knot.KnotClient.main(KnotClient.java:28)