407 lines
16 KiB
Diff
407 lines
16 KiB
Diff
From 2075295c3698f8e5aee39c7f017b591b85ad9ba2 Mon Sep 17 00:00:00 2001
|
|
From: Josh Brobst <josh@brob.st>
|
|
Date: Sat, 31 Dec 2022 14:41:44 -0500
|
|
Subject: [PATCH 1/2] [Backport] http: decode transfer encoding first
|
|
|
|
Offering: RTOS
|
|
CVE: CVE-2023-23916
|
|
Reference: https://github.com/curl/curl/commit/aa6e7a1f45d3d82ceaf58534bcc5ac409abbd0a0
|
|
DTS/AR: DTS2023021511961
|
|
type: LTS
|
|
reason: The unencoding stack is added to as Transfer-Encoding and
|
|
Content-Encoding fields are encountered with no distinction between the
|
|
two, meaning the stack will be incorrect if, e.g., the message has both
|
|
fields and a non-chunked Transfer-Encoding comes first. This commit
|
|
fixes this by ordering the stack with transfer encodings first.
|
|
|
|
Reviewed-by: Patrick Monnerat
|
|
Closes #10187
|
|
|
|
(cherry picked from commit aa6e7a1f45d3d82ceaf58534bcc5ac409abbd0a0)
|
|
|
|
Conflicts:
|
|
lib/content_encoding.c
|
|
lib/content_encoding.h
|
|
tests/data/Makefile.inc
|
|
Signed-off-by: chenzanyu <chenzanyu@huawei.com>
|
|
---
|
|
lib/content_encoding.c | 39 +++++---
|
|
lib/content_encoding.h | 5 +-
|
|
tests/data/Makefile.inc | 4 +-
|
|
tests/data/test1277 | 206 ++++++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 239 insertions(+), 15 deletions(-)
|
|
create mode 100644 tests/data/test1277
|
|
|
|
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
|
|
index e78cd1cab..37aceccdf 100644
|
|
--- a/lib/content_encoding.c
|
|
+++ b/lib/content_encoding.c
|
|
@@ -5,7 +5,7 @@
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
+ * Copyright (C) 1998 - 2023, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
*
|
|
* This software is licensed as described in the file COPYING, which
|
|
* you should have received as part of this distribution. The terms
|
|
@@ -968,7 +968,8 @@ static const struct content_encoding error_encoding = {
|
|
static struct contenc_writer *
|
|
new_unencoding_writer(struct Curl_easy *data,
|
|
const struct content_encoding *handler,
|
|
- struct contenc_writer *downstream)
|
|
+ struct contenc_writer *downstream,
|
|
+ int order)
|
|
{
|
|
size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
|
|
struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);
|
|
@@ -976,6 +977,7 @@ new_unencoding_writer(struct Curl_easy *data,
|
|
if(writer) {
|
|
writer->handler = handler;
|
|
writer->downstream = downstream;
|
|
+ writer->order = order;
|
|
if(handler->init_writer(data, writer)) {
|
|
free(writer);
|
|
writer = NULL;
|
|
@@ -1031,10 +1033,11 @@ static const struct content_encoding *find_encoding(const char *name,
|
|
/* Set-up the unencoding stack from the Content-Encoding header value.
|
|
* See RFC 7231 section 3.1.2.2. */
|
|
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
- const char *enclist, int maybechunked)
|
|
+ const char *enclist, int is_transfer)
|
|
{
|
|
struct SingleRequest *k = &data->req;
|
|
int counter = 0;
|
|
+ unsigned int order = is_transfer? 2: 1;
|
|
|
|
do {
|
|
const char *name;
|
|
@@ -1051,7 +1054,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
namelen = enclist - name + 1;
|
|
|
|
/* Special case: chunked encoding is handled at the reader level. */
|
|
- if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
|
|
+ if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) {
|
|
k->chunk = TRUE; /* chunks coming our way. */
|
|
Curl_httpchunk_init(data); /* init our chunky engine. */
|
|
}
|
|
@@ -1060,7 +1063,8 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
struct contenc_writer *writer;
|
|
|
|
if(!k->writer_stack) {
|
|
- k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL);
|
|
+ k->writer_stack = new_unencoding_writer(data, &client_encoding,
|
|
+ NULL, 0);
|
|
|
|
if(!k->writer_stack)
|
|
return CURLE_OUT_OF_MEMORY;
|
|
@@ -1075,10 +1079,23 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
return CURLE_BAD_CONTENT_ENCODING;
|
|
}
|
|
/* Stack the unencoding stage. */
|
|
- writer = new_unencoding_writer(data, encoding, k->writer_stack);
|
|
- if(!writer)
|
|
- return CURLE_OUT_OF_MEMORY;
|
|
- k->writer_stack = writer;
|
|
+ if(order >= k->writer_stack->order) {
|
|
+ writer = new_unencoding_writer(data, encoding,
|
|
+ k->writer_stack, order);
|
|
+ if(!writer)
|
|
+ return CURLE_OUT_OF_MEMORY;
|
|
+ k->writer_stack = writer;
|
|
+ }
|
|
+ else {
|
|
+ struct contenc_writer *w = k->writer_stack;
|
|
+ while(w->downstream && order < w->downstream->order)
|
|
+ w = w->downstream;
|
|
+ writer = new_unencoding_writer(data, encoding,
|
|
+ w->downstream, order);
|
|
+ if(!writer)
|
|
+ return CURLE_OUT_OF_MEMORY;
|
|
+ w->downstream = writer;
|
|
+ }
|
|
}
|
|
} while(*enclist);
|
|
|
|
@@ -1088,11 +1105,11 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
#else
|
|
/* Stubs for builds without HTTP. */
|
|
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
- const char *enclist, int maybechunked)
|
|
+ const char *enclist, int is_transfer)
|
|
{
|
|
(void) data;
|
|
(void) enclist;
|
|
- (void) maybechunked;
|
|
+ (void) is_transfer;
|
|
return CURLE_NOT_BUILT_IN;
|
|
}
|
|
|
|
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
|
|
index acfd0c27b..010297ca4 100644
|
|
--- a/lib/content_encoding.h
|
|
+++ b/lib/content_encoding.h
|
|
@@ -7,7 +7,7 @@
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
+ * Copyright (C) 1998 - 2023, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
*
|
|
* This software is licensed as described in the file COPYING, which
|
|
* you should have received as part of this distribution. The terms
|
|
@@ -27,6 +27,7 @@ struct contenc_writer {
|
|
const struct content_encoding *handler; /* Encoding handler. */
|
|
struct contenc_writer *downstream; /* Downstream writer. */
|
|
void *params; /* Encoding-specific storage (variable length). */
|
|
+ unsigned int order; /* Ordering within writer stack. */
|
|
};
|
|
|
|
/* Content encoding writer. */
|
|
@@ -45,7 +46,7 @@ struct content_encoding {
|
|
|
|
|
|
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
|
- const char *enclist, int maybechunked);
|
|
+ const char *enclist, int is_transfer);
|
|
CURLcode Curl_unencode_write(struct Curl_easy *data,
|
|
struct contenc_writer *writer,
|
|
const char *buf, size_t nbytes);
|
|
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
|
|
index ae7df4add..831cdb800 100644
|
|
--- a/tests/data/Makefile.inc
|
|
+++ b/tests/data/Makefile.inc
|
|
@@ -5,7 +5,7 @@
|
|
# | (__| |_| | _ <| |___
|
|
# \___|\___/|_| \_\_____|
|
|
#
|
|
-# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
+# Copyright (C) 1998 - 2023, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
#
|
|
# This software is licensed as described in the file COPYING, which
|
|
# you should have received as part of this distribution. The terms
|
|
@@ -159,7 +159,7 @@ test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 \
|
|
test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \
|
|
test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \
|
|
test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \
|
|
-test1272 test1273 \
|
|
+test1272 test1273 test1277 \
|
|
\
|
|
test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
|
|
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
|
|
diff --git a/tests/data/test1277 b/tests/data/test1277
|
|
new file mode 100644
|
|
index 000000000..b705569d0
|
|
--- /dev/null
|
|
+++ b/tests/data/test1277
|
|
@@ -0,0 +1,206 @@
|
|
+<testcase>
|
|
+<info>
|
|
+<keywords>
|
|
+HTTP
|
|
+HTTP GET
|
|
+compressed
|
|
+Transfer-Encoding
|
|
+Content-Encoding
|
|
+</keywords>
|
|
+</info>
|
|
+#
|
|
+# Server-side
|
|
+<reply>
|
|
+<data base64="yes">
|
|
+SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDI5IE5vdiAyMDA0IDIxOjU2OjUzIEdNVA0KU2Vy
|
|
+dmVyOiBBcGFjaGUvMS4zLjMxIChEZWJpYW4gR05VL0xpbnV4KSBtb2RfZ3ppcC8xLjMuMjYuMWEg
|
|
+UEhQLzQuMy45LTEgbW9kX3NzbC8yLjguMjAgT3BlblNTTC8wLjkuN2QgbW9kX3BlcmwvMS4yOQ0K
|
|
+VmFyeTogQWNjZXB0LUVuY29kaW5nDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1J
|
|
+U08tODg1OS0xDQpUcmFuc2Zlci1FbmNvZGluZzogZ3ppcCwgY2h1bmtlZA0KQ29udGVudC1FbmNv
|
|
+ZGluZzogZGVmbGF0ZQ0KDQo1MjINCh+LCAAHgbBjAv8BCwX0+nja3VjbbuM2EH03kH9g/dQCtm62
|
|
+EzlwtChy2QTNNsHaBbpPBi3RNhtJFEjKuTz02zuUKImxHK93g74ESGJy5pzD4QxJk5l8ekpitCFc
|
|
+UJaedV3L6SKShiyi6eqsezO96/v+aNx3u5+CzuSXi7vz2bf7S5Rx9g8JZT+mQgIQTb9NZ5dfUHct
|
|
+ZXZq20tOxDohWFopkfYChw8kjexl0tc80XesoRXJqAuiW1pBB6HKptpNb06jwD12vYltGEpEhCWZ
|
|
+4ygigBiP/b7j9z0XOcNTxz31xhPb8BuEPFMfUeA5zrDvOn3XR4536sHPQFMqxKs4UpyQuVgzLoMw
|
|
+53EdjmFv45d5HBdwhNMIxXTRphYQHR4RoZY6Z0lSUlKCJGO1AMf8GS0ZR2FMSSr7gkYE/fX1FkmO
|
|
+U7GEilowi0bIUN4ZDKIC4XIEpVqpcFXfJY2JOOrkQnXUGOI5lfjJQjcSiTzLQF+g69nsvlf8nfbQ
|
|
+FbSPOldF++LmfNZDs8vbPy/h8/bid4Bd3dxe9orhP9/dX19+hTYM8EhiiKmU6mdMyJ5u5tAKGXug
|
|
+RBTaKM9ihiMYApZanpComXUPZViIR8Yj1YTI0jxZFPbp9PaoExIu6ZKGUFcw/UE4+JgoQ4FqPMEI
|
|
+xbQgGxl7JJxER53Fc5WkHpJr8mbGq7JYR53ZGqgIw++CpmozCUhtnWqVYAabDnnOUSfG6SrHKyKK
|
|
+GEi6oZylCQwgQEeX0FgbGypxTOXzXISMk2B04g+t0cnE3rJvgTPCQ5AMBpZ7bGAr8xYa5vMAe21s
|
|
+IAuTXtcsy2PMm7GOR2OIYQjLedvTIlQDugPLd18RXodiOMpgnNErtBEOx8W54VsjZ2LrjumZhywH
|
|
+Xc+tvNrwClMO4g9qjDGAyBci5DSTcESKYKBOh9emEgalT8P1XO3l4IIscR7LiW0aSxjUf14dYBmU
|
|
+Pdh5aFYnpa3Wiz2xW6xGbM0S8rYQLGDKSxV1eNomQ+vWAo2mXL0cLgdgraRojcjixTtcBMBaRNEa
|
|
+kReaHS4CYC2iaI1IuIY9RmK2OlyqpmjBRqKR5VlyuCCAtZSiNSIRWRwuAmAtomiNCBNPh4sAWIso
|
|
+mlEvEanz8gdqVhKqumm6scxzDmkTJNDrt+oahdmIHyjJRlTF2AhDRN0cDldRaC1TEBudhHLO+OFK
|
|
+JV5rabJZ14QFVa2gWXpiCoccpODLzcz+G53D6QEpo3mCbkvHxK4QGq++p+Sck5jUmWuZ5/r+FpxY
|
|
+rmfBBekN9xtsda86OXb8UYtYXbDaHHUv2n1x2gUs52LvmswEzlECE14zOZdr+KqGnLVMJRLnEm4y
|
|
+og6p7Ffd2qBPYJxSEqOpJCl8w68mtulsUaBKu+v+7wKvIqKKbCBbdM5iEtw9poTXuMJURWqboVY9
|
|
+YVzJOE1oiqU5O8nhhlDUBgpad1pezzve5x7s5e5zur6/l+vuHReWxv6o97rd4+E+93gv2R/v9Tp7
|
|
+3e7oO3F/J7D9kQ1aY5f3u+3yw5rI4MkEDzG4jtY6tfEZyeeMnHU5CeF1oGzqJVUvygZnbmRHDbXL
|
|
+sZOo7y3gPhmqYux07WQaj7MWdfvh9hZXUqk2FNjhzo5+1bep33Zqldh6pzWIt/PGinsbjv+/pDk/
|
|
+nbHh4J0ZU++rj58o1xuM3Hdk6gWeYh8/SwPPGZ68I0vXhCYRjj9+oobD0cB7R6LCPjz1xc/kybDo
|
|
+s77+r1DQqZvNf8f+A904jtHT7+gYCwUAAA0KMA0KDQo=
|
|
+</data>
|
|
+
|
|
+
|
|
+<datacheck>
|
|
+HTTP/1.1 200 OK
|
|
+Date: Mon, 29 Nov 2004 21:56:53 GMT
|
|
+Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29
|
|
+Vary: Accept-Encoding
|
|
+Content-Type: text/html; charset=ISO-8859-1
|
|
+Transfer-Encoding: gzip, chunked
|
|
+Content-Encoding: deflate
|
|
+
|
|
+<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
+<!DOCTYPE project-listing SYSTEM "http://freshmeat.net/backend/fm-projects-0.4.dtd">
|
|
+<project-listing>
|
|
+ <project>
|
|
+ <project_id>1612</project_id>
|
|
+ <date_added>1998-08-21 04:01:29</date_added>
|
|
+ <date_updated>2004-10-18 02:22:23</date_updated>
|
|
+ <projectname_short>curl</projectname_short>
|
|
+ <projectname_full>curl and libcurl</projectname_full>
|
|
+ <desc_short>Command line tool and library for client-side URL transfers.</desc_short>
|
|
+ <desc_full>curl and libcurl is a tool for transferring files
|
|
+using URL syntax. It supports HTTP, HTTPS, FTP,
|
|
+FTPS, DICT, TELNET, LDAP, FILE, and GOPHER, as
|
|
+well as HTTP-post, HTTP-put, cookies, FTP upload,
|
|
+resumed transfers, passwords, portnumbers, SSL
|
|
+certificates, Kerberos, and proxies. It is powered
|
|
+by libcurl, the client-side URL transfer library.
|
|
+There are bindings to libcurl for over 20
|
|
+languages and environments.
|
|
+</desc_full>
|
|
+ <vitality_score>5784.57</vitality_score>
|
|
+ <vitality_percent>3.16</vitality_percent>
|
|
+ <vitality_rank>169</vitality_rank>
|
|
+ <popularity_score>6594.54</popularity_score>
|
|
+ <popularity_percent>13.81</popularity_percent>
|
|
+ <popularity_rank>105</popularity_rank>
|
|
+ <rating>8.50</rating>
|
|
+ <rating_count>21</rating_count>
|
|
+ <rating_rank>183</rating_rank>
|
|
+ <subscriptions>323</subscriptions>
|
|
+ <branch_name>Default</branch_name>
|
|
+ <url_project_page>http://freshmeat.net/projects/curl/</url_project_page>
|
|
+ <url_homepage>http://freshmeat.net/redir/curl/1612/url_homepage/</url_homepage>
|
|
+ <url_tgz>http://freshmeat.net/redir/curl/1612/url_tgz/</url_tgz>
|
|
+ <url_bz2>http://freshmeat.net/redir/curl/1612/url_bz2/</url_bz2>
|
|
+ <url_zip>http://freshmeat.net/redir/curl/1612/url_zip/</url_zip>
|
|
+ <url_changelog>http://freshmeat.net/redir/curl/1612/url_changelog/</url_changelog>
|
|
+ <url_rpm>http://freshmeat.net/redir/curl/1612/url_rpm/</url_rpm>
|
|
+ <url_deb>http://freshmeat.net/redir/curl/1612/url_deb/</url_deb>
|
|
+ <url_osx>http://freshmeat.net/redir/curl/1612/url_osx/</url_osx>
|
|
+ <url_bsdport>http://freshmeat.net/redir/curl/1612/url_bsdport/</url_bsdport>
|
|
+ <url_purchase></url_purchase>
|
|
+ <url_cvs>http://freshmeat.net/redir/curl/1612/url_cvs/</url_cvs>
|
|
+ <url_list>http://freshmeat.net/redir/curl/1612/url_list/</url_list>
|
|
+ <url_mirror>http://freshmeat.net/redir/curl/1612/url_mirror/</url_mirror>
|
|
+ <url_demo></url_demo>
|
|
+ <license>MIT/X Consortium License</license>
|
|
+ <latest_release>
|
|
+ <latest_release_version>7.12.2</latest_release_version>
|
|
+ <latest_release_id>176085</latest_release_id>
|
|
+ <latest_release_date>2004-10-18 02:22:23</latest_release_date>
|
|
+ </latest_release>
|
|
+ <screenshot_thumb></screenshot_thumb>
|
|
+ <authors>
|
|
+ <author>
|
|
+ <author_name>Daniel Stenberg</author_name>
|
|
+ <author_url>http://freshmeat.net/~bagder/</author_url>
|
|
+ <author_role>Owner</author_role>
|
|
+ </author>
|
|
+ </authors>
|
|
+ <descriminators>
|
|
+ <trove_id>12</trove_id>
|
|
+ <trove_id>226</trove_id>
|
|
+ <trove_id>3</trove_id>
|
|
+ <trove_id>2</trove_id>
|
|
+ <trove_id>188</trove_id>
|
|
+ <trove_id>216</trove_id>
|
|
+ <trove_id>200</trove_id>
|
|
+ <trove_id>220</trove_id>
|
|
+ <trove_id>164</trove_id>
|
|
+ <trove_id>90</trove_id>
|
|
+ <trove_id>89</trove_id>
|
|
+ <trove_id>809</trove_id>
|
|
+ <trove_id>150</trove_id>
|
|
+ <trove_id>224</trove_id>
|
|
+ <trove_id>900</trove_id>
|
|
+ <trove_id>839</trove_id>
|
|
+ </descriminators>
|
|
+ <dependencies>
|
|
+ <dependency type="recommended">
|
|
+ <dependency_release_id>0</dependency_release_id>
|
|
+ <dependency_branch_id>7464</dependency_branch_id>
|
|
+ <dependency_project_id>7464</dependency_project_id>
|
|
+ <dependency_project_title>OpenSSL (Default)</dependency_project_title>
|
|
+ </dependency>
|
|
+ <dependency type="optional">
|
|
+ <dependency_release_id>0</dependency_release_id>
|
|
+ <dependency_branch_id>0</dependency_branch_id>
|
|
+ <dependency_project_id>7443</dependency_project_id>
|
|
+ <dependency_project_title>OpenLDAP</dependency_project_title>
|
|
+ </dependency>
|
|
+ <dependency type="optional">
|
|
+ <dependency_release_id>0</dependency_release_id>
|
|
+ <dependency_branch_id>0</dependency_branch_id>
|
|
+ <dependency_project_id>12351</dependency_project_id>
|
|
+ <dependency_project_title>zlib</dependency_project_title>
|
|
+ </dependency>
|
|
+ <dependency type="optional">
|
|
+ <dependency_release_id>0</dependency_release_id>
|
|
+ <dependency_branch_id>0</dependency_branch_id>
|
|
+ <dependency_project_id>32047</dependency_project_id>
|
|
+ <dependency_project_title>Heimdal</dependency_project_title>
|
|
+ </dependency>
|
|
+ <dependency type="optional">
|
|
+ <dependency_release_id>0</dependency_release_id>
|
|
+ <dependency_branch_id>0</dependency_branch_id>
|
|
+ <dependency_project_id>44532</dependency_project_id>
|
|
+ <dependency_project_title>c-ares</dependency_project_title>
|
|
+ </dependency>
|
|
+ </dependencies>
|
|
+ </project>
|
|
+</project-listing>
|
|
+</datacheck>
|
|
+
|
|
+</reply>
|
|
+
|
|
+#
|
|
+# Client-side
|
|
+<client>
|
|
+<features>
|
|
+libz
|
|
+</features>
|
|
+<server>
|
|
+http
|
|
+</server>
|
|
+ <name>
|
|
+HTTP GET with both content and transfer encoding
|
|
+ </name>
|
|
+ <command>
|
|
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --tr-encoding --compressed
|
|
+</command>
|
|
+</client>
|
|
+
|
|
+#
|
|
+# Verify data after the test has been "shot"
|
|
+<verify>
|
|
+<strippart>
|
|
+s/^Accept-Encoding: [a-zA-Z, ]*/Accept-Encoding: xxx/
|
|
+</strippart>
|
|
+<protocol>
|
|
+GET /%TESTNUMBER HTTP/1.1
|
|
+Host: %HOSTIP:%HTTPPORT
|
|
+User-Agent: curl/%VERSION
|
|
+Accept: */*
|
|
+Connection: TE
|
|
+TE: gzip
|
|
+Accept-Encoding: xxx
|
|
+
|
|
+</protocol>
|
|
+</verify>
|
|
+</testcase>
|
|
--
|
|
2.35.1.windows.2
|
|
|