162 lines
6.0 KiB
Diff
162 lines
6.0 KiB
Diff
From c6223b3b0f3d8e6a37b5775b44eeded02e9c3ea7 Mon Sep 17 00:00:00 2001
|
|
From: Sebastian Pipping <sebastian@pipping.org>
|
|
Date: Sat, 17 Apr 2021 17:26:17 +0200
|
|
Subject: [PATCH] xmlwf: Add support for custom attack protection parameters
|
|
|
|
---
|
|
xmlwf/xmltchar.h | 5 +++-
|
|
xmlwf/xmlwf.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
|
|
xmlwf/xmlwf_helpgen.py | 8 +++++
|
|
3 files changed, 82 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xmlwf/xmltchar.h b/xmlwf/xmltchar.h
|
|
index 4843fbe..30283d0 100644
|
|
--- a/xmlwf/xmltchar.h
|
|
+++ b/xmlwf/xmltchar.h
|
|
@@ -55,6 +55,8 @@
|
|
# define tmain wmain
|
|
# define tremove _wremove
|
|
# define tchar wchar_t
|
|
+# define tcstof wcstof
|
|
+# define tcstoull wcstoull
|
|
#else /* not XML_UNICODE */
|
|
# define T(x) x
|
|
# define ftprintf fprintf
|
|
@@ -72,4 +74,6 @@
|
|
# define tmain main
|
|
# define tremove remove
|
|
# define tchar char
|
|
+# define tcstof strtof
|
|
+# define tcstoull strtoull
|
|
#endif /* not XML_UNICODE */
|
|
diff --git a/xmlwf/xmlwf.c b/xmlwf/xmlwf.c
|
|
index 2b86966..342d6c5 100644
|
|
--- a/xmlwf/xmlwf.c
|
|
+++ b/xmlwf/xmlwf.c
|
|
@@ -46,6 +46,8 @@
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
+#include <math.h> /* for isnan */
|
|
+#include <errno.h>
|
|
|
|
#include "expat.h"
|
|
#include "codepage.h"
|
|
@@ -905,6 +907,12 @@ usage(const XML_Char *prog, int rc) {
|
|
T(" -t write no XML output for [t]iming of plain parsing\n")
|
|
T(" -N enable adding doctype and [n]otation declarations\n")
|
|
T("\n")
|
|
+ T("billion laughs attack protection:\n")
|
|
+ T(" NOTE: If you ever need to increase these values for non-attack payload, please file a bug report.\n")
|
|
+ T("\n")
|
|
+ T(" -a FACTOR set maximum tolerated [a]mplification factor (default: 100.0)\n")
|
|
+ T(" -b BYTES set number of output [b]ytes needed to activate (default: 8 MiB)\n")
|
|
+ T("\n")
|
|
T("info arguments:\n")
|
|
T(" -h show this [h]elp message and exit\n")
|
|
T(" -v show program's [v]ersion number and exit\n")
|
|
@@ -953,6 +961,11 @@ tmain(int argc, XML_Char **argv) {
|
|
int useNamespaces = 0;
|
|
int requireStandalone = 0;
|
|
int requiresNotations = 0;
|
|
+
|
|
+ float attackMaximumAmplification = -1.0f; /* signaling "not set" */
|
|
+ unsigned long long attackThresholdBytes;
|
|
+ XML_Bool attackThresholdGiven = XML_FALSE;
|
|
+
|
|
enum XML_ParamEntityParsing paramEntityParsing
|
|
= XML_PARAM_ENTITY_PARSING_NEVER;
|
|
int useStdin = 0;
|
|
@@ -1032,6 +1045,49 @@ tmain(int argc, XML_Char **argv) {
|
|
case T('v'):
|
|
showVersion(argv[0]);
|
|
return 0;
|
|
+ case T('a'): {
|
|
+ const XML_Char *valueText = NULL;
|
|
+ XMLWF_SHIFT_ARG_INTO(valueText, argc, argv, i, j);
|
|
+
|
|
+ errno = 0;
|
|
+ XML_Char *afterValueText = (XML_Char *)valueText;
|
|
+ attackMaximumAmplification = tcstof(valueText, &afterValueText);
|
|
+ if ((errno != 0) || (afterValueText[0] != T('\0'))
|
|
+ || isnan(attackMaximumAmplification)
|
|
+ || (attackMaximumAmplification < 1.0f)) {
|
|
+ // This prevents tperror(..) from reporting misleading "[..]: Success"
|
|
+ errno = ERANGE;
|
|
+ tperror(T("invalid amplification limit") T(
|
|
+ " (needs a floating point number greater or equal than 1.0)"));
|
|
+ exit(2);
|
|
+ }
|
|
+#ifndef XML_DTD
|
|
+ ftprintf(stderr, T("Warning: Given amplification limit ignored") T(
|
|
+ ", xmlwf has been compiled without DTD support.\n"));
|
|
+#endif
|
|
+ break;
|
|
+ }
|
|
+ case T('b'): {
|
|
+ const XML_Char *valueText = NULL;
|
|
+ XMLWF_SHIFT_ARG_INTO(valueText, argc, argv, i, j);
|
|
+
|
|
+ errno = 0;
|
|
+ XML_Char *afterValueText = (XML_Char *)valueText;
|
|
+ attackThresholdBytes = tcstoull(valueText, &afterValueText, 10);
|
|
+ if ((errno != 0) || (afterValueText[0] != T('\0'))) {
|
|
+ // This prevents tperror(..) from reporting misleading "[..]: Success"
|
|
+ errno = ERANGE;
|
|
+ tperror(T("invalid ignore threshold")
|
|
+ T(" (needs an integer from 0 to 2^64-1)"));
|
|
+ exit(2);
|
|
+ }
|
|
+ attackThresholdGiven = XML_TRUE;
|
|
+#ifndef XML_DTD
|
|
+ ftprintf(stderr, T("Warning: Given attack threshold ignored") T(
|
|
+ ", xmlwf has been compiled without DTD support.\n"));
|
|
+#endif
|
|
+ break;
|
|
+ }
|
|
case T('\0'):
|
|
if (j > 1) {
|
|
i++;
|
|
@@ -1062,6 +1118,19 @@ tmain(int argc, XML_Char **argv) {
|
|
exit(1);
|
|
}
|
|
|
|
+ if (attackMaximumAmplification != -1.0f) {
|
|
+#ifdef XML_DTD
|
|
+ XML_SetBillionLaughsAttackProtectionMaximumAmplification(
|
|
+ parser, attackMaximumAmplification);
|
|
+#endif
|
|
+ }
|
|
+ if (attackThresholdGiven) {
|
|
+#ifdef XML_DTD
|
|
+ XML_SetBillionLaughsAttackProtectionActivationThreshold(
|
|
+ parser, attackThresholdBytes);
|
|
+#endif
|
|
+ }
|
|
+
|
|
if (requireStandalone)
|
|
XML_SetNotStandaloneHandler(parser, notStandalone);
|
|
XML_SetParamEntityParsing(parser, paramEntityParsing);
|
|
diff --git a/xmlwf/xmlwf_helpgen.py b/xmlwf/xmlwf_helpgen.py
|
|
index 8ec8d4e..c2a527f 100755
|
|
--- a/xmlwf/xmlwf_helpgen.py
|
|
+++ b/xmlwf/xmlwf_helpgen.py
|
|
@@ -73,6 +73,14 @@ output_mode.add_argument('-m', action='store_true', help='write [m]eta XML, not
|
|
output_mode.add_argument('-t', action='store_true', help='write no XML output for [t]iming of plain parsing')
|
|
output_related.add_argument('-N', action='store_true', help='enable adding doctype and [n]otation declarations')
|
|
|
|
+billion_laughs = parser.add_argument_group('billion laughs attack protection',
|
|
+ description='NOTE: '
|
|
+ 'If you ever need to increase these values '
|
|
+ 'for non-attack payload, please file a bug report.')
|
|
+billion_laughs.add_argument('-a', metavar='FACTOR',
|
|
+ help='set maximum tolerated [a]mplification factor (default: 100.0)')
|
|
+billion_laughs.add_argument('-b', metavar='BYTES', help='set number of output [b]ytes needed to activate (default: 8 MiB)')
|
|
+
|
|
parser.add_argument('files', metavar='FILE', nargs='*', help='files to process (default: STDIN)')
|
|
|
|
info = parser.add_argument_group('info arguments')
|
|
--
|
|
1.8.3.1
|
|
|