[ https://issues.apache.org/jira/browse/JOHNZON-190?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16635832#comment-16635832 ]
Otavio Goncalves de Santana commented on JOHNZON-190: ----------------------------------------------------- Hey [~romain.manni-bucau] could you move it to the branch: maintenance_1.0.x also, please? https://github.com/apache/johnzon/pull/28 > Issues when call close method more than twice using Queue as buffer strategy. > ----------------------------------------------------------------------------- > > Key: JOHNZON-190 > URL: https://issues.apache.org/jira/browse/JOHNZON-190 > Project: Johnzon > Issue Type: Bug > Components: JSON-B > Affects Versions: 1.1.10 > Reporter: Otavio Goncalves de Santana > Assignee: Romain Manni-Bucau > Priority: Major > Fix For: 1.1.11 > > > Title: Issues when calling the close method more than twice using Queue as a > buffer strategy. > > Hello everyone. > > I would like to report a bug within JsonGeneratorImpl. In the > JsonGeneratorImpl has the BufferStrategy.BufferProvider<char[]> as an > attribute. > This BufferStrategy.BufferProvider either [put the buffer in the > Queue|https://github.com/apache/johnzon/blob/d7a4a2f9de8c39b84fbb8b73b13c6f7f6514a9cf/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java#L466], > whose uses the release *method*, and > [feed|https://github.com/apache/johnzon/blob/d7a4a2f9de8c39b84fbb8b73b13c6f7f6514a9cf/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java#L72] > the buffer using the *newBuffer* method. > > As consequences of this behavior there are two failures: > > # Waste of memory issue > > The code below, it will put the same value in the queue six times. > {code:java} > public class App { > public static void main(String[] args) throws IOException { > Path path = Paths.get("generated.json"); > OutputStream out = Files.newOutputStream(path); > JsonGenerator jsonGen = Json.createGenerator(out); > jsonGen.writeStartObject(); > jsonGen.write("false", JsonValue.FALSE); > jsonGen.write("true", JsonValue.TRUE); > jsonGen.writeEnd(); > jsonGen.close(); > jsonGen.close(); > jsonGen.close(); > jsonGen.close(); > jsonGen.close(); > jsonGen.close(); > } > } > {code} > Doing a malicious code such as below, it will use a huge number of memory. > {code:java} > public class App1 { > public static void main(String[] args) throws IOException { > Path path = Paths.get("generated.json"); > OutputStream out = Files.newOutputStream(path); > JsonGenerator jsonGen = Json.createGenerator(out); > jsonGen.writeStartObject(); > jsonGen.write("false", JsonValue.FALSE); > jsonGen.write("true", JsonValue.TRUE); > jsonGen.writeEnd(); > while (true) { > jsonGen.close(); > } > } > } > {code} > # The security issue > It uses the value in the queue as a buffer; thereby, it is a security failure > once a request can read information from another application, thus, an > isolation issue. > {code:java} > public class App2 { > public static void main(String[] args) throws Exception { > Path path = Paths.get("generated2.json"); > OutputStream out = Files.newOutputStream(path); > JsonGenerator jsonGen = Json.createGenerator(out); > jsonGen.writeStartObject(); > jsonGen.write("keyA", JsonValue.FALSE); > jsonGen.write("keyB", JsonValue.TRUE); > jsonGen.writeEnd(); > jsonGen.close(); > Path path3 = Paths.get("generated3.json"); > OutputStream out2 = Files.newOutputStream(path3); > JsonGenerator jsonGen2 = Json.createGenerator(out2); > jsonGen2.writeStartObject(); > Field fieldBuffer = jsonGen2.getClass().getDeclaredField("buffer"); > fieldBuffer.setAccessible(true); > char[] buffer = (char[]) fieldBuffer.get(jsonGen); > String json = String.valueOf(buffer); > System.out.println(json); > jsonGen2.flush(); > } > } > {code} > # Race condition issue: > As the code below shows, given a mistake of twice close, To class can write > using the same buffer, thereby, a write JSON mistake. > {code:java} > public class App3 { > public static void main(String[] args) throws IOException { > Path path = Paths.get("generated.json"); > OutputStream out = Files.newOutputStream(path); > JsonGenerator jsonGen = Json.createGenerator(out); > jsonGen.writeStartObject(); > jsonGen.write("false", JsonValue.FALSE); > jsonGen.write("true", JsonValue.TRUE); > jsonGen.writeEnd(); > jsonGen.close(); > jsonGen.close(); > Path path2 = Paths.get("generated2.json"); > OutputStream out2 = Files.newOutputStream(path2); > JsonGenerator jsonGen2 = Json.createGenerator(out2); > Path path3 = Paths.get("generated3.json"); > OutputStream out3 = Files.newOutputStream(path3); > JsonGenerator jsonGen3 = Json.createGenerator(out3); > jsonGen2.writeStartObject(); > jsonGen2.write("false1", JsonValue.FALSE); > jsonGen2.write("true2", JsonValue.TRUE); > jsonGen2.writeEnd(); > jsonGen3.writeStartObject(); > jsonGen3.write("false3", JsonValue.FALSE); > jsonGen3.write("true4", JsonValue.TRUE); > jsonGen3.writeEnd(); > jsonGen2.close(); > jsonGen3.close(); > } > } > {code} > Output > {code:json} > Generated.json: {"false":false,"true":true} > Generated2.json: {"false3":false,"true4":true} > Generated3.json: {"false3":false,"true4":true} > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)