1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import com.google.protobuf.ArrayDecoders.Registers;
34 import java.io.IOException;
35 import junit.framework.TestCase;
36 
37 public class ArrayDecodersTest extends TestCase {
38 
39   private static final int TAG = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
40   private static final ByteString NEGATIVE_SIZE_0 = generateNegativeLength(0);
41   private static final ByteString NEGATIVE_SIZE_1 = generateNegativeLength(1);
42 
43   private Registers registers;
44 
45   @Override
setUp()46   public void setUp() {
47     registers = new Registers();
48     registers.int1 = TAG;
49   }
50 
testException_decodeString()51   public void testException_decodeString() {
52     try {
53       ArrayDecoders.decodeString(NEGATIVE_SIZE_0.toByteArray(), 0, registers);
54       fail();
55     } catch (InvalidProtocolBufferException expected) {
56     }
57   }
58 
testException_decodeStringRequireUtf8()59   public void testException_decodeStringRequireUtf8() {
60     try {
61       ArrayDecoders.decodeStringRequireUtf8(NEGATIVE_SIZE_0.toByteArray(), 0, registers);
62       fail();
63     } catch (InvalidProtocolBufferException expected) {
64     }
65   }
66 
testException_decodeBytes()67   public void testException_decodeBytes() {
68     try {
69       ArrayDecoders.decodeBytes(NEGATIVE_SIZE_0.toByteArray(), 0, registers);
70       fail();
71     } catch (InvalidProtocolBufferException expected) {
72     }
73   }
74 
testException_decodeStringList_first()75   public void testException_decodeStringList_first() {
76     try {
77       ArrayDecoders.decodeStringList(
78           TAG,
79           NEGATIVE_SIZE_0.toByteArray(),
80           0,
81           NEGATIVE_SIZE_0.size(),
82           new ProtobufArrayList<Object>(),
83           registers);
84       fail();
85     } catch (InvalidProtocolBufferException expected) {
86     }
87   }
88 
testException_decodeStringList_second()89   public void testException_decodeStringList_second() {
90     try {
91       ArrayDecoders.decodeStringList(
92           TAG,
93           NEGATIVE_SIZE_1.toByteArray(),
94           0,
95           NEGATIVE_SIZE_1.size(),
96           new ProtobufArrayList<Object>(),
97           registers);
98       fail();
99     } catch (InvalidProtocolBufferException expected) {
100     }
101   }
102 
testException_decodeStringListRequireUtf8_first()103   public void testException_decodeStringListRequireUtf8_first() {
104     try {
105       ArrayDecoders.decodeStringListRequireUtf8(
106           TAG,
107           NEGATIVE_SIZE_0.toByteArray(),
108           0,
109           NEGATIVE_SIZE_0.size(),
110           new ProtobufArrayList<Object>(),
111           registers);
112       fail();
113     } catch (InvalidProtocolBufferException expected) {
114     }
115   }
116 
testException_decodeStringListRequireUtf8_second()117   public void testException_decodeStringListRequireUtf8_second() {
118     try {
119       ArrayDecoders.decodeStringListRequireUtf8(
120           TAG,
121           NEGATIVE_SIZE_1.toByteArray(),
122           0,
123           NEGATIVE_SIZE_1.size(),
124           new ProtobufArrayList<Object>(),
125           registers);
126       fail();
127     } catch (InvalidProtocolBufferException expected) {
128     }
129   }
130 
testException_decodeBytesList_first()131   public void testException_decodeBytesList_first() {
132     try {
133       ArrayDecoders.decodeBytesList(
134           TAG,
135           NEGATIVE_SIZE_0.toByteArray(),
136           0,
137           NEGATIVE_SIZE_0.size(),
138           new ProtobufArrayList<Object>(),
139           registers);
140       fail();
141     } catch (InvalidProtocolBufferException expected) {
142     }
143   }
144 
testException_decodeBytesList_second()145   public void testException_decodeBytesList_second() {
146     try {
147       ArrayDecoders.decodeBytesList(
148           TAG,
149           NEGATIVE_SIZE_1.toByteArray(),
150           0,
151           NEGATIVE_SIZE_1.size(),
152           new ProtobufArrayList<Object>(),
153           registers);
154       fail();
155     } catch (InvalidProtocolBufferException expected) {
156     }
157   }
158 
testException_decodeUnknownField()159   public void testException_decodeUnknownField() {
160     try {
161       ArrayDecoders.decodeUnknownField(
162           TAG,
163           NEGATIVE_SIZE_0.toByteArray(),
164           0,
165           NEGATIVE_SIZE_0.size(),
166           UnknownFieldSetLite.newInstance(),
167           registers);
168       fail();
169     } catch (InvalidProtocolBufferException expected) {
170     }
171   }
172 
testException_decodeHugeField()173   public void testException_decodeHugeField() {
174     byte[] badBytes =
175         new byte[] {
176           (byte) 0x80, (byte) 0xFF, (byte) 0xFF, (byte) 0xEF, 0x73, 0x74, 0x69, 0x6E, 0x67
177         };
178     try {
179       ArrayDecoders.decodeUnknownField(
180           TAG, badBytes, 0, badBytes.length, UnknownFieldSetLite.newInstance(), registers);
181       fail();
182     } catch (InvalidProtocolBufferException expected) {
183     }
184 
185     try {
186       ArrayDecoders.decodeBytes(badBytes, 0, registers);
187       fail();
188     } catch (InvalidProtocolBufferException expected) {
189     }
190 
191     byte[] badBytesList =
192         new byte[] {
193           0x01,
194           0x77,
195           0x0A,
196           (byte) 0x80,
197           (byte) 0xFF,
198           (byte) 0xFF,
199           (byte) 0xEF,
200           0x73,
201           0x74,
202           0x69,
203           0x6E,
204           0x67
205         };
206     try {
207       ArrayDecoders.decodeBytesList(
208           TAG, badBytesList, 0, badBytes.length, new ProtobufArrayList<>(), registers);
209       fail();
210     } catch (InvalidProtocolBufferException expected) {
211     }
212   }
213 
generateNegativeLength(int count)214   private static ByteString generateNegativeLength(int count) {
215     try {
216       ByteString.Output byteStringOutput = ByteString.newOutput();
217       CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput);
218 
219       // Write out count - 1 valid 0 length fields; we only write out tags after the field since
220       // ArrayDecoders expects the first tag to already have been parsed.
221       for (int i = 0; i < count; i++) {
222         codedOutput.writeInt32NoTag(0);
223         codedOutput.writeInt32NoTag(TAG);
224       }
225 
226       // Write out a negative length
227       codedOutput.writeInt32NoTag(-1);
228 
229       codedOutput.flush();
230 
231       return byteStringOutput.toByteString();
232     } catch (IOException e) {
233       throw new RuntimeException(e);
234     }
235   }
236 }
237