Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/sun/security/util/ManifestDigester/DigestInput.java
41152 views
1
/*
2
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import java.io.ByteArrayOutputStream;
25
import java.io.IOException;
26
import java.security.MessageDigest;
27
import java.util.ArrayList;
28
import java.util.Arrays;
29
import java.util.List;
30
import java.util.jar.Attributes.Name;
31
import java.util.stream.Collectors;
32
33
import sun.security.util.ManifestDigester;
34
35
import org.testng.annotations.DataProvider;
36
import org.testng.annotations.Factory;
37
import org.testng.annotations.BeforeMethod;
38
import org.testng.annotations.AfterTest;
39
import org.testng.annotations.Test;
40
41
import static java.nio.charset.StandardCharsets.UTF_8;
42
import static org.testng.Assert.*;
43
44
/**
45
* @test
46
* @bug 8217375
47
* @modules java.base/sun.security.util
48
* @compile ../../tools/jarsigner/Utils.java
49
* @run testng DigestInput
50
* @summary Checks that the manifest main attributes and entry digests are the
51
* same as before resolution of bug 8217375 which means they treat some white
52
* space different for oldStyle or digestWorkaround except for the blank line
53
* at the end of the manifest file for digestWorkaround.
54
*/
55
public class DigestInput {
56
57
/**
58
* Filters some test cases for calibrating expected digests with previous
59
* implementation. TODO: Delete this after calibrating with old sources.
60
*/
61
static final boolean FIXED_8217375 = true; // FIXME
62
63
/**
64
* {@link ManifestDigester.Entry#digestWorkaround} should not feed the
65
* trailing blank line into the digester. Before resolution of 8217375 it
66
* fed the trailing blank line into the digest if the second line break
67
* was at the end of the file due to <pre>
68
* if (allBlank || (i == len-1)) {
69
* if (i == len-1)
70
* pos.endOfSection = i;
71
* else
72
* pos.endOfSection = last;
73
* </pre> in {@link ManifestDigester#findSection}. In that case at the end
74
* of the manifest file, {@link ManifestDigester.Entry#digestWorkaround}
75
* would have produced the same digest as
76
* {@link ManifestDigester.Entry#digest} which was wrong and without effect
77
* at best.
78
* <p>
79
* Once this fix is accepted, this flag can be removed along with
80
* {@link #assertDigestEqualsCatchWorkaroundBroken}.
81
*/
82
static final boolean FIXED_8217375_EOF_ENDOFSECTION = FIXED_8217375;
83
84
static final String SECTION_NAME = "some individual section name";
85
86
@DataProvider(name = "parameters")
87
public static Object[][] parameters() {
88
List<Object[]> tests = new ArrayList<>();
89
for (String lineBreak : new String[] { "\n", "\r", "\r\n" }) {
90
if ("\r".equals(lineBreak) && !FIXED_8217375) continue;
91
for (int addLB = 0; addLB <= 4; addLB++) {
92
for (int numSecs = 0; numSecs <= 4; numSecs++) {
93
for (boolean otherSec : new Boolean[] { false, true }) {
94
for (boolean oldStyle : new Boolean[] { false, true }) {
95
for (boolean workaround :
96
new Boolean[] { false, true }) {
97
tests.add(new Object[] {
98
lineBreak, addLB, numSecs, otherSec,
99
oldStyle, workaround
100
});
101
}
102
}
103
}
104
}
105
}
106
}
107
return tests.toArray(new Object[tests.size()][]);
108
}
109
110
@Factory(dataProvider = "parameters")
111
public static Object[] createTests(
112
String lineBreak, int additionalLineBreaks,
113
int numberOfSections, boolean hasOtherSection,
114
boolean oldStyle, boolean digestWorkaround) {
115
return new Object[] { new DigestInput(lineBreak,
116
additionalLineBreaks, numberOfSections, hasOtherSection,
117
oldStyle, digestWorkaround)
118
};
119
}
120
121
final String lineBreak;
122
final int additionalLineBreaks; // number of blank lines delimiting section
123
final int numberOfSections;
124
final boolean hasOtherSection;
125
final boolean oldStyle;
126
final boolean digestWorkaround;
127
128
public DigestInput(
129
String lineBreak, int additionalLineBreaks,
130
int numberOfSections, boolean hasOtherSection,
131
boolean oldStyle, boolean digestWorkaround) {
132
this.lineBreak = lineBreak;
133
this.additionalLineBreaks = additionalLineBreaks;
134
this.numberOfSections = numberOfSections;
135
this.hasOtherSection = hasOtherSection;
136
this.oldStyle = oldStyle;
137
this.digestWorkaround = digestWorkaround;
138
}
139
140
@BeforeMethod
141
public void verbose() {
142
System.out.println("-".repeat(72));
143
System.out.println("lineBreak = " +
144
Utils.escapeStringWithNumbers(lineBreak));
145
System.out.println("additionalLineBreaks = " + additionalLineBreaks);
146
System.out.println("numberOfSections = " + numberOfSections);
147
System.out.println("hasOtherSection = " + hasOtherSection);
148
System.out.println("oldStyle = " + oldStyle);
149
System.out.println("digestWorkaround = " + digestWorkaround);
150
System.out.println("-".repeat(72));
151
}
152
153
byte[] rawManifestBytes() {
154
return (
155
Name.MANIFEST_VERSION + ": 1.0" + lineBreak +
156
"OldStyle0: no trailing space" + lineBreak +
157
"OldStyle1: trailing space " + lineBreak +
158
"OldStyle2: two trailing spaces " + lineBreak +
159
lineBreak.repeat(additionalLineBreaks) +
160
(
161
"Name: " + SECTION_NAME + lineBreak +
162
"OldStyle0: no trailing space" + lineBreak +
163
"OldStyle1: trailing space " + lineBreak +
164
"OldStyle2: two trailing spaces " + lineBreak +
165
lineBreak.repeat(additionalLineBreaks)
166
).repeat(numberOfSections) +
167
(hasOtherSection ?
168
"Name: unrelated trailing section" + lineBreak +
169
"OldStyle0: no trailing space" + lineBreak +
170
"OldStyle1: trailing space " + lineBreak +
171
"OldStyle2: two trailing spaces " + lineBreak +
172
lineBreak.repeat(additionalLineBreaks)
173
: "")
174
).getBytes(UTF_8);
175
}
176
177
byte[] expectedMainAttrsDigest(boolean digestWorkaround) {
178
return (
179
Name.MANIFEST_VERSION + ": 1.0" + lineBreak +
180
"OldStyle0: no trailing space" + lineBreak +
181
"OldStyle1: trailing space" +
182
(!oldStyle || !lineBreak.startsWith("\r") || digestWorkaround ?
183
" " : "") + lineBreak +
184
"OldStyle2: two trailing spaces " +
185
(!oldStyle || !lineBreak.startsWith("\r") || digestWorkaround ?
186
" " : "") + lineBreak +
187
(
188
(
189
!digestWorkaround
190
|| (
191
additionalLineBreaks == 1
192
&& numberOfSections == 0
193
&& !hasOtherSection
194
&& (
195
digestWorkaround
196
&& !FIXED_8217375_EOF_ENDOFSECTION
197
)
198
)
199
) && (
200
additionalLineBreaks > 0
201
|| numberOfSections > 0
202
|| hasOtherSection
203
)
204
? lineBreak : "")
205
).getBytes(UTF_8);
206
}
207
208
byte[] expectedIndividualSectionDigest(boolean digestWorkaround) {
209
if (numberOfSections == 0) return null;
210
return (
211
(
212
"Name: " + SECTION_NAME + lineBreak +
213
"OldStyle0: no trailing space" + lineBreak +
214
"OldStyle1: trailing space" +
215
(!oldStyle || !lineBreak.startsWith("\r")
216
|| digestWorkaround ? " " : "") + lineBreak +
217
"OldStyle2: two trailing spaces " +
218
(!oldStyle || !lineBreak.startsWith("\r")
219
|| digestWorkaround ? " " : "") + lineBreak +
220
(
221
(
222
!digestWorkaround
223
) && (
224
additionalLineBreaks > 0
225
)
226
? lineBreak : "")
227
).repeat(numberOfSections) +
228
(
229
additionalLineBreaks == 1
230
&& !hasOtherSection
231
&& digestWorkaround
232
&& !FIXED_8217375_EOF_ENDOFSECTION
233
? lineBreak : "")
234
).getBytes(UTF_8);
235
}
236
237
class EchoMessageDigest extends MessageDigest {
238
239
ByteArrayOutputStream buf;
240
241
EchoMessageDigest() {
242
super("echo");
243
}
244
245
@Override
246
protected void engineReset() {
247
buf = new ByteArrayOutputStream();
248
}
249
250
@Override
251
protected void engineUpdate(byte input) {
252
buf.write(input);
253
}
254
255
@Override
256
protected void engineUpdate(byte[] i, int o, int l) {
257
buf.write(i, o, l);
258
}
259
260
@Override protected byte[] engineDigest() {
261
return buf.toByteArray();
262
}
263
264
}
265
266
byte[] digestMainAttributes(byte[] mfBytes) throws Exception {
267
Utils.echoManifest(mfBytes, "going to digest main attributes of");
268
269
ManifestDigester md = new ManifestDigester(mfBytes);
270
ManifestDigester.Entry entry =
271
md.get(ManifestDigester.MF_MAIN_ATTRS, oldStyle);
272
MessageDigest digester = new EchoMessageDigest();
273
return digestWorkaround ?
274
entry.digestWorkaround(digester) : entry.digest(digester);
275
}
276
277
byte[] digestIndividualSection(byte[] mfBytes) throws Exception {
278
Utils.echoManifest(mfBytes,
279
"going to digest section " + SECTION_NAME + " of");
280
281
ManifestDigester md = new ManifestDigester(mfBytes);
282
ManifestDigester.Entry entry = md.get(SECTION_NAME, oldStyle);
283
if (entry == null) {
284
return null;
285
}
286
MessageDigest digester = new EchoMessageDigest();
287
return digestWorkaround ?
288
entry.digestWorkaround(digester) : entry.digest(digester);
289
}
290
291
292
/**
293
* Checks that the manifest main attributes digest is the same as before.
294
*/
295
@Test
296
public void testMainAttributesDigest() throws Exception {
297
byte[] mfRaw = rawManifestBytes();
298
byte[] digest = digestMainAttributes(mfRaw);
299
byte[] expectedDigest = expectedMainAttrsDigest(digestWorkaround);
300
301
// the individual section will be digested along with the main
302
// attributes if not properly delimited with a blank line
303
if (additionalLineBreaks == 0
304
&& (numberOfSections > 0 || hasOtherSection)) {
305
assertNotEquals(digest, expectedDigest);
306
return;
307
}
308
309
byte[] expectedDigestNoWorkaround = expectedMainAttrsDigest(false);
310
311
// assertDigestEquals(digest, expectedDigest); // FIXME
312
assertDigestEqualsCatchWorkaroundBroken(
313
digest, expectedDigest, expectedDigestNoWorkaround);
314
}
315
316
/**
317
* Checks that an individual section digest is the same as before.
318
*/
319
@Test
320
public void testIndividualSectionDigest() throws Exception {
321
byte[] mfRaw = rawManifestBytes();
322
byte[] digest = digestIndividualSection(mfRaw);
323
324
// no digest will be produced for an individual section that is not
325
// properly section delimited with a blank line.
326
byte[] expectedDigest =
327
additionalLineBreaks == 0 ? null :
328
expectedIndividualSectionDigest(digestWorkaround);
329
330
byte[] expectedDigestNoWorkaround =
331
additionalLineBreaks == 0 ? null :
332
expectedIndividualSectionDigest(false);
333
334
// assertDigestEquals(digest, expectedDigest); // FIXME
335
assertDigestEqualsCatchWorkaroundBroken(
336
digest, expectedDigest, expectedDigestNoWorkaround);
337
}
338
339
static int firstDiffPos = Integer.MAX_VALUE;
340
341
/**
342
* @see FIXED_8217375_EOF_ENDOFSECTION
343
*/
344
void assertDigestEqualsCatchWorkaroundBroken(
345
byte[] actual, byte[] expected, byte[] expectedNoWorkaround)
346
throws IOException {
347
try {
348
assertDigestEquals(actual, expected);
349
} catch (AssertionError e) {
350
if (digestWorkaround && FIXED_8217375_EOF_ENDOFSECTION &&
351
Arrays.equals(expected, expectedNoWorkaround)) {
352
// if digests with and without workaround are the same anyway
353
// the workaround has failed and could not have worked with
354
// the same digest as produced without workaround before
355
// which would not match either because equal.
356
return;
357
}
358
fail("failed also without digestWorkaound", e);
359
}
360
}
361
362
void assertDigestEquals(byte[] actual, byte[] expected) throws IOException {
363
if (actual == null && expected == null) return;
364
Utils.echoManifest(actual, "actual digest");
365
Utils.echoManifest(expected, "expected digest");
366
for (int i = 0; i < actual.length && i < expected.length; i++) {
367
if (actual[i] != expected[i]) {
368
firstDiffPos = Math.min(firstDiffPos, i);
369
verbose();
370
fail("found first difference in current test"
371
+ " at position " + i);
372
}
373
}
374
if (actual.length != expected.length) {
375
int diffPos = Math.min(actual.length, expected.length);
376
firstDiffPos = Math.min(firstDiffPos, diffPos);
377
verbose();
378
fail("found first difference in current test"
379
+ " at position " + diffPos + " after one digest end");
380
}
381
assertEquals(actual, expected);
382
}
383
384
@AfterTest
385
public void reportFirstDiffPos() {
386
System.err.println("found first difference in all tests"
387
+ " at position " + firstDiffPos);
388
}
389
390
}
391
392