blob: 15729a73df186d53529cdd3335ddd29680f90772 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package org.bouncycastle.cms.jcajce;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.InflaterInputStream;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.InputExpander;
import org.bouncycastle.operator.InputExpanderProvider;
import org.bouncycastle.util.io.StreamOverflowException;
public class ZlibExpanderProvider
implements InputExpanderProvider
{
private final long limit;
/**
* Base constructor. Create an expander which will not limit the size of any objects expanded in the stream.
*/
public ZlibExpanderProvider()
{
this.limit = -1;
}
/**
* Create a provider which caps the number of expanded bytes that can be produced when the
* compressed stream is parsed.
*
* @param limit max number of bytes allowed in an expanded stream.
*/
public ZlibExpanderProvider(long limit)
{
this.limit = limit;
}
public InputExpander get(final AlgorithmIdentifier algorithm)
{
return new InputExpander()
{
public AlgorithmIdentifier getAlgorithmIdentifier()
{
return algorithm;
}
public InputStream getInputStream(InputStream comIn)
{
InputStream s = new InflaterInputStream(comIn);
if (limit >= 0)
{
s = new LimitedInputStream(s, limit);
}
return s;
}
};
}
private static class LimitedInputStream
extends FilterInputStream
{
private long remaining;
public LimitedInputStream(InputStream input, long limit)
{
super(input);
this.remaining = limit;
}
public int read()
throws IOException
{
// Only a single 'extra' byte will ever be read
if (remaining >= 0)
{
int b = super.in.read();
if (b < 0 || --remaining >= 0)
{
return b;
}
}
throw new StreamOverflowException("expanded byte limit exceeded");
}
public int read(byte[] buf, int off, int len)
throws IOException
{
if (len < 1)
{
// This will give correct exceptions/returns for strange lengths
return super.read(buf, off, len);
}
if (remaining < 1)
{
// Will either return EOF or throw exception
read();
return -1;
}
/*
* Limit the underlying request to 'remaining' bytes. This ensures the
* caller will see the full 'limit' bytes before getting an exception.
* Also, only one extra byte will ever be read.
*/
int actualLen = (remaining > len ? len : (int)remaining);
int numRead = super.in.read(buf, off, actualLen);
if (numRead > 0)
{
remaining -= numRead;
}
return numRead;
}
}
}
|