FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
RecursiveExtractor/RecursiveExtractor/ResourceGovernor.cs at main · microsoft/RecursiveExtractor · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
microsoft
/
RecursiveExtractor
Public
Notifications
You must be signed in to change notification settings
Fork
35
Star
219
Code
Issues
19
Pull requests
3
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
RecursiveExtractor
/
RecursiveExtractor
/
ResourceGovernor.cs
Copy path
More file actions
More file actions
Latest commit
History
History
History
102 lines (90 loc) · 3.85 KB
Breadcrumbs
RecursiveExtractor
/
RecursiveExtractor
/
ResourceGovernor.cs
Copy path
File metadata and controls
102 lines (90 loc) · 3.85 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
using
NLog
;
using
System
;
using
System
.
Diagnostics
;
using
System
.
IO
;
using
System
.
Threading
;
namespace
Microsoft
.
CST
.
RecursiveExtractor
{
/// <summary>
/// Class that keeps track of bytes processed and time spent processing. Used to Detect ZipBombs etc.
/// </summary>
public
class
ResourceGovernor
{
private
readonly
ExtractorOptions
options
;
private
readonly
NLog
.
Logger
Logger
=
NLog
.
LogManager
.
GetCurrentClassLogger
(
)
;
/// <summary>
/// Create a governor with the given options.
/// </summary>
/// <param name="opts"></param>
public
ResourceGovernor
(
ExtractorOptions
opts
)
{
options
=
opts
??
new
ExtractorOptions
(
)
;
GovernorStopwatch
=
new
Stopwatch
(
)
;
}
internal
void
ResetResourceGovernor
(
Stream
stream
)
{
Logger
.
Trace
(
"ResetResourceGovernor()"
)
;
if
(
stream
==
null
)
{
throw
new
ArgumentNullException
(
nameof
(
stream
)
,
"Stream must not be null."
)
;
}
GovernorStopwatch
=
Stopwatch
.
StartNew
(
)
;
// Default value is we take MaxExtractedBytes (meaning, ratio is not defined)
CurrentOperationProcessedBytesLeft
=
options
.
MaxExtractedBytes
;
if
(
options
.
MaxExtractedBytesRatio
>
0
)
{
long
streamLength
;
try
{
streamLength
=
stream
.
Length
;
}
catch
(
Exception
)
{
throw
new
ArgumentException
(
"Unable to get length of stream."
)
;
}
// Ratio *is* defined, so the max value would be based on the stream length
var
maxViaRatio
=
(
long
)
(
options
.
MaxExtractedBytesRatio
*
streamLength
)
;
// Assign the samller of the two, accounting for MaxExtractedBytes == 0 means, 'no limit'.
CurrentOperationProcessedBytesLeft
=
Math
.
Min
(
maxViaRatio
,
options
.
MaxExtractedBytes
>
0
?
options
.
MaxExtractedBytes
:
long
.
MaxValue
)
;
}
}
/// <summary>
/// Stores the number of bytes left before we abort (denial of service).
/// </summary>
private
long
CurrentOperationProcessedBytesLeft
=
-
1
;
/// <summary>
/// Adjust the amount of bytes remaining.
/// </summary>
/// <param name="ChangeAmount"></param>
internal
void
AdjustRemainingBytes
(
long
ChangeAmount
)
{
lock
(
this
)
{
CurrentOperationProcessedBytesLeft
+=
ChangeAmount
;
}
}
/// <summary>
/// Times extraction operations to avoid denial of service.
/// </summary>
internal
Stopwatch
GovernorStopwatch
;
/// <summary>
/// Checks to ensure we haven't extracted too many bytes, or taken too long. This exists primarily
/// to mitigate the risks of quines (archives that contain themselves) and zip bombs (specially
/// constructed to expand to huge sizes).
/// Ref: https://alf.nu/ZipQuine
/// </summary>
/// <param name="additionalBytes"> </param>
internal
void
CheckResourceGovernor
(
long
additionalBytes
=
0
)
{
Logger
.
ConditionalTrace
(
"CheckResourceGovernor(duration={0}, bytes={1})"
,
GovernorStopwatch
.
Elapsed
.
TotalMilliseconds
,
CurrentOperationProcessedBytesLeft
)
;
if
(
options
.
EnableTiming
&&
GovernorStopwatch
.
Elapsed
>
options
.
Timeout
)
{
throw
new
TimeoutException
(
string
.
Format
(
$
"Processing timeout exceeded:
{
GovernorStopwatch
.
Elapsed
.
TotalMilliseconds
}
ms."
)
)
;
}
if
(
CurrentOperationProcessedBytesLeft
-
additionalBytes
<
0
)
{
throw
new
OverflowException
(
"Too many bytes extracted, exceeding limit."
)
;
}
}
}
}
Back
|
FazBrowse Home
|
New Git URL