1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dexfuzz.rawdex; 18 19 import dexfuzz.Log; 20 21 import java.io.IOException; 22 import java.nio.charset.StandardCharsets; 23 24 public class StringDataItem implements RawDexObject { 25 private int size; 26 private String data; 27 private byte[] dataAsBytes; 28 private boolean writeRawBytes; 29 30 @Override read(DexRandomAccessFile file)31 public void read(DexRandomAccessFile file) throws IOException { 32 file.getOffsetTracker().getNewOffsettable(file, this); 33 size = file.readUleb128(); 34 if (size != 0) { 35 dataAsBytes = file.readDexUtf(size); 36 data = new String(dataAsBytes, StandardCharsets.US_ASCII); 37 if (size != data.length()) { 38 Log.warn("Don't have full support for decoding MUTF-8 yet, DEX file " 39 + "may be incorrectly mutated. Avoid using this test case for now."); 40 writeRawBytes = true; 41 } 42 } else { 43 // Read past the null byte. 44 file.readByte(); 45 } 46 } 47 48 @Override write(DexRandomAccessFile file)49 public void write(DexRandomAccessFile file) throws IOException { 50 file.getOffsetTracker().updatePositionOfNextOffsettable(file); 51 file.writeUleb128(size); 52 if (size > 0) { 53 if (writeRawBytes) { 54 file.writeDexUtf(dataAsBytes); 55 } else { 56 file.writeDexUtf(data.getBytes(StandardCharsets.US_ASCII)); 57 } 58 } else { 59 // Write out the null byte. 60 file.writeByte(0); 61 } 62 } 63 64 @Override incrementIndex(IndexUpdateKind kind, int insertedIdx)65 public void incrementIndex(IndexUpdateKind kind, int insertedIdx) { 66 // Do nothing. 67 } 68 setSize(int size)69 public void setSize(int size) { 70 this.size = size; 71 } 72 getSize()73 public int getSize() { 74 return size; 75 } 76 setString(String data)77 public void setString(String data) { 78 this.data = data; 79 } 80 getString()81 public String getString() { 82 if (writeRawBytes) { 83 Log.warn("Reading a string that hasn't been properly decoded! Returning empty string."); 84 return ""; 85 } 86 return data; 87 } 88 } 89