mirror of
https://github.com/curl/curl.git
synced 2025-09-04 03:15:04 +03:00
Compare commits
3 Commits
b23e0f01af
...
54098af721
Author | SHA1 | Date | |
---|---|---|---|
|
54098af721 | ||
|
4a3ed6fc16 | ||
|
f92d9c0c5f |
|
@ -332,6 +332,12 @@ Callback for wildcard matching. See CURLOPT_FNMATCH_FUNCTION(3)
|
||||||
|
|
||||||
Follow HTTP redirects. See CURLOPT_FOLLOWLOCATION(3)
|
Follow HTTP redirects. See CURLOPT_FOLLOWLOCATION(3)
|
||||||
|
|
||||||
|
## CURLOPT_FORBID_RETRY_ON_REUSE
|
||||||
|
|
||||||
|
Prevent curl from transparently retry a transfer on a new connection when a
|
||||||
|
previously reused connection was reset or otherwise no longer unavailable.
|
||||||
|
See CURLOPT_FORBID_RETRY_ON_REUSE(3)
|
||||||
|
|
||||||
## CURLOPT_FORBID_REUSE
|
## CURLOPT_FORBID_REUSE
|
||||||
|
|
||||||
Prevent subsequent connections from reusing this. See CURLOPT_FORBID_REUSE(3)
|
Prevent subsequent connections from reusing this. See CURLOPT_FORBID_REUSE(3)
|
||||||
|
|
106
docs/libcurl/opts/CURLOPT_FORBID_RETRY_ON_REUSE.md
Normal file
106
docs/libcurl/opts/CURLOPT_FORBID_RETRY_ON_REUSE.md
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
---
|
||||||
|
c: Copyright (C) 2025 Hewlett Packard Enterprise Development LP
|
||||||
|
SPDX-License-Identifier: curl
|
||||||
|
Title: CURLOPT_FORBID_RETRY_ON_REUSE
|
||||||
|
Section: 3
|
||||||
|
Source: libcurl
|
||||||
|
See-also:
|
||||||
|
- CURLOPT_FRESH_CONNECT (3)
|
||||||
|
- CURLOPT_FORBID_REUSE (3)
|
||||||
|
Protocol:
|
||||||
|
- All
|
||||||
|
Added-in: 8.16.0
|
||||||
|
---
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
CURLOPT_FORBID_RETRY_ON_REUSE - prevent retry in case of reused connection is reset
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
|
||||||
|
~~~c
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FORBID_RETRY_ON_REUSE,
|
||||||
|
long forbid_retry);
|
||||||
|
~~~
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
Pass a long. Set *forbid_retry* to 1 to prevent libcurl from resubmitting a
|
||||||
|
transfer on a new connection when the previous reused connection was reset.
|
||||||
|
Instead, the reset is returned to the caller as a `CURLE_RECV_ERROR`.
|
||||||
|
|
||||||
|
This option only affects retry decision if the connection used to perform
|
||||||
|
the request (and from which CURL received a TCP reset) is reused.
|
||||||
|
|
||||||
|
Normally, libcurl considers connection resets on reused connections as a
|
||||||
|
transient timing issue. The reset event is only visible to curl at the time
|
||||||
|
libcurl attempts to issue transfer on that connection. As a result,
|
||||||
|
sometimes libcurl may issue more than 1 identical transfers in a row on
|
||||||
|
different connections with a single `curl_easy_perform()` call. Caller is
|
||||||
|
not informed about any previous transfer attempts that may or may not have
|
||||||
|
arrived at the server before the reset happened.
|
||||||
|
|
||||||
|
This can break transactional application-level protocols if the protocol
|
||||||
|
state machine considers connection state changes as part of state
|
||||||
|
transition edges, or the protocol involves non-idempotent requests with
|
||||||
|
side effects.
|
||||||
|
|
||||||
|
Before introduction of this option, the only way to avoid unobservable
|
||||||
|
retries was to set CURLOPT_FORBID_REUSE(3) to 1. However, without
|
||||||
|
connection reuse and keepalive, the application pays significant
|
||||||
|
overhead from the TCP and TLS handshake for every transfer. This option
|
||||||
|
decouples implicit retry behavior from connection reuse, allowing the
|
||||||
|
application to benefit from connection reuse without risking unobservable
|
||||||
|
retries.
|
||||||
|
|
||||||
|
Set to 0 to have libcurl transparently retry the transfer on a new
|
||||||
|
connection if the reused connection was reset (default behavior).
|
||||||
|
|
||||||
|
# DEFAULT
|
||||||
|
|
||||||
|
0
|
||||||
|
|
||||||
|
# %PROTOCOLS%
|
||||||
|
|
||||||
|
# EXAMPLE
|
||||||
|
|
||||||
|
~~~c
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FORBID_RETRY_ON_REUSE, 1L);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This request will establish a connection and retained it for reuse
|
||||||
|
* after the transfer is done.
|
||||||
|
*/
|
||||||
|
curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* Wait long enough for the server to drop connection. */
|
||||||
|
sleep(60);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl will fail this request from the reset instead of
|
||||||
|
* transmitting the same transfer again over a new connection.
|
||||||
|
*/
|
||||||
|
curl_easy_perform(curl);
|
||||||
|
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~~~
|
||||||
|
|
||||||
|
# %AVAILABILITY%
|
||||||
|
|
||||||
|
# RETURN VALUE
|
||||||
|
|
||||||
|
curl_easy_setopt(3) returns a CURLcode indicating success or error.
|
||||||
|
|
||||||
|
CURLE_OK (0) means everything was OK, non-zero means an error occurred, see
|
||||||
|
libcurl-errors(3).
|
|
@ -185,6 +185,7 @@ man_MANS = \
|
||||||
CURLOPT_FNMATCH_DATA.3 \
|
CURLOPT_FNMATCH_DATA.3 \
|
||||||
CURLOPT_FNMATCH_FUNCTION.3 \
|
CURLOPT_FNMATCH_FUNCTION.3 \
|
||||||
CURLOPT_FOLLOWLOCATION.3 \
|
CURLOPT_FOLLOWLOCATION.3 \
|
||||||
|
CURLOPT_FORBID_RETRY_ON_REUSE.3 \
|
||||||
CURLOPT_FORBID_REUSE.3 \
|
CURLOPT_FORBID_REUSE.3 \
|
||||||
CURLOPT_FRESH_CONNECT.3 \
|
CURLOPT_FRESH_CONNECT.3 \
|
||||||
CURLOPT_FTP_ACCOUNT.3 \
|
CURLOPT_FTP_ACCOUNT.3 \
|
||||||
|
|
|
@ -646,6 +646,7 @@ CURLOPT_FILETIME 7.5
|
||||||
CURLOPT_FNMATCH_DATA 7.21.0
|
CURLOPT_FNMATCH_DATA 7.21.0
|
||||||
CURLOPT_FNMATCH_FUNCTION 7.21.0
|
CURLOPT_FNMATCH_FUNCTION 7.21.0
|
||||||
CURLOPT_FOLLOWLOCATION 7.1
|
CURLOPT_FOLLOWLOCATION 7.1
|
||||||
|
CURLOPT_FORBID_RETRY_ON_REUSE 8.16.0
|
||||||
CURLOPT_FORBID_REUSE 7.7
|
CURLOPT_FORBID_REUSE 7.7
|
||||||
CURLOPT_FRESH_CONNECT 7.7
|
CURLOPT_FRESH_CONNECT 7.7
|
||||||
CURLOPT_FTP_ACCOUNT 7.13.0
|
CURLOPT_FTP_ACCOUNT 7.13.0
|
||||||
|
|
|
@ -2258,6 +2258,10 @@ typedef enum {
|
||||||
/* set TLS supported signature algorithms */
|
/* set TLS supported signature algorithms */
|
||||||
CURLOPT(CURLOPT_SSL_SIGNATURE_ALGORITHMS, CURLOPTTYPE_STRINGPOINT, 328),
|
CURLOPT(CURLOPT_SSL_SIGNATURE_ALGORITHMS, CURLOPTTYPE_STRINGPOINT, 328),
|
||||||
|
|
||||||
|
/* prevent transparent retries on a new connection when a previously
|
||||||
|
* reused connection was reset or otherwise no longer unavailable. */
|
||||||
|
CURLOPT(CURLOPT_FORBID_RETRY_ON_REUSE, CURLOPTTYPE_LONG, 329),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unused */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ const struct curl_easyoption Curl_easyopts[] = {
|
||||||
{"FNMATCH_DATA", CURLOPT_FNMATCH_DATA, CURLOT_CBPTR, 0},
|
{"FNMATCH_DATA", CURLOPT_FNMATCH_DATA, CURLOT_CBPTR, 0},
|
||||||
{"FNMATCH_FUNCTION", CURLOPT_FNMATCH_FUNCTION, CURLOT_FUNCTION, 0},
|
{"FNMATCH_FUNCTION", CURLOPT_FNMATCH_FUNCTION, CURLOT_FUNCTION, 0},
|
||||||
{"FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION, CURLOT_LONG, 0},
|
{"FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION, CURLOT_LONG, 0},
|
||||||
|
{"FORBID_RETRY_ON_REUSE", CURLOPT_FORBID_RETRY_ON_REUSE, CURLOT_LONG, 0},
|
||||||
{"FORBID_REUSE", CURLOPT_FORBID_REUSE, CURLOT_LONG, 0},
|
{"FORBID_REUSE", CURLOPT_FORBID_REUSE, CURLOT_LONG, 0},
|
||||||
{"FRESH_CONNECT", CURLOPT_FRESH_CONNECT, CURLOT_LONG, 0},
|
{"FRESH_CONNECT", CURLOPT_FRESH_CONNECT, CURLOT_LONG, 0},
|
||||||
{"FTPAPPEND", CURLOPT_APPEND, CURLOT_LONG, CURLOT_FLAG_ALIAS},
|
{"FTPAPPEND", CURLOPT_APPEND, CURLOT_LONG, CURLOT_FLAG_ALIAS},
|
||||||
|
@ -380,6 +381,6 @@ const struct curl_easyoption Curl_easyopts[] = {
|
||||||
*/
|
*/
|
||||||
int Curl_easyopts_check(void)
|
int Curl_easyopts_check(void)
|
||||||
{
|
{
|
||||||
return (CURLOPT_LASTENTRY % 10000) != (328 + 1);
|
return (CURLOPT_LASTENTRY % 10000) != (329 + 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -452,6 +452,13 @@ static CURLcode setopt_bool(struct Curl_easy *data, CURLoption option,
|
||||||
*/
|
*/
|
||||||
s->reuse_forbid = enabled;
|
s->reuse_forbid = enabled;
|
||||||
break;
|
break;
|
||||||
|
case CURLOPT_FORBID_RETRY_ON_REUSE:
|
||||||
|
/**
|
||||||
|
* No retry under any circumstances even when a reset happens on a reused
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
s->retry_on_reuse_forbid = enabled;
|
||||||
|
break;
|
||||||
case CURLOPT_FRESH_CONNECT:
|
case CURLOPT_FRESH_CONNECT:
|
||||||
/*
|
/*
|
||||||
* This transfer shall not use a previously cached connection but
|
* This transfer shall not use a previously cached connection but
|
||||||
|
|
|
@ -667,7 +667,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
if((data->req.bytecount + data->req.headerbytecount == 0) &&
|
if((data->req.bytecount + data->req.headerbytecount == 0) &&
|
||||||
conn->bits.reuse &&
|
conn->bits.reuse && conn->bits.retry_on_reuse &&
|
||||||
(!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
|
(!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
|
||||||
#ifndef CURL_DISABLE_RTSP
|
#ifndef CURL_DISABLE_RTSP
|
||||||
&& (data->set.rtspreq != RTSPREQ_RECEIVE)
|
&& (data->set.rtspreq != RTSPREQ_RECEIVE)
|
||||||
|
|
|
@ -3514,6 +3514,10 @@ static CURLcode create_conn(struct Curl_easy *data,
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
|
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
|
||||||
conn->bits.tunnel_proxy = TRUE;
|
conn->bits.tunnel_proxy = TRUE;
|
||||||
|
|
||||||
|
/* Carry over the no-retry-on-reuse into connection bits. */
|
||||||
|
conn->bits.retry_on_reuse = !data->set.retry_on_reuse_forbid;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
|
|
|
@ -379,6 +379,8 @@ struct ConnectBits {
|
||||||
/* always modify bits.close with the connclose() and connkeep() macros! */
|
/* always modify bits.close with the connclose() and connkeep() macros! */
|
||||||
BIT(close); /* if set, we close the connection after this request */
|
BIT(close); /* if set, we close the connection after this request */
|
||||||
BIT(reuse); /* if set, this is a reused connection */
|
BIT(reuse); /* if set, this is a reused connection */
|
||||||
|
BIT(retry_on_reuse); /* if set, a reused connection after connection reset
|
||||||
|
is allowed to retry the request */
|
||||||
BIT(altused); /* this is an alt-svc "redirect" */
|
BIT(altused); /* this is an alt-svc "redirect" */
|
||||||
BIT(conn_to_host); /* if set, this connection has a "connect to host"
|
BIT(conn_to_host); /* if set, this connection has a "connect to host"
|
||||||
that overrides the host in the URL */
|
that overrides the host in the URL */
|
||||||
|
@ -1605,6 +1607,7 @@ struct UserDefined {
|
||||||
#endif
|
#endif
|
||||||
BIT(reuse_forbid); /* forbidden to be reused, close after use */
|
BIT(reuse_forbid); /* forbidden to be reused, close after use */
|
||||||
BIT(reuse_fresh); /* do not reuse an existing connection */
|
BIT(reuse_fresh); /* do not reuse an existing connection */
|
||||||
|
BIT(retry_on_reuse_forbid); /* do not retry under connection reset */
|
||||||
BIT(no_signal); /* do not use any signal/alarm handler */
|
BIT(no_signal); /* do not use any signal/alarm handler */
|
||||||
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
|
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
|
||||||
BIT(ignorecl); /* ignore content length */
|
BIT(ignorecl); /* ignore content length */
|
||||||
|
|
|
@ -1398,6 +1398,8 @@ static CURLcode add_parallel_transfers(CURLM *multi, CURLSH *share,
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
if(getenv("CURL_FORBID_REUSE"))
|
if(getenv("CURL_FORBID_REUSE"))
|
||||||
(void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L);
|
(void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L);
|
||||||
|
if(getenv("CURL_FORBID_RETRY_ON_REUSE"))
|
||||||
|
(void)curl_easy_setopt(per->curl, CURLOPT_FORBID_RETRY_ON_REUSE, 1L);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mcode = curl_multi_add_handle(multi, per->curl);
|
mcode = curl_multi_add_handle(multi, per->curl);
|
||||||
|
@ -1868,6 +1870,8 @@ static CURLcode serial_transfers(CURLSH *share)
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
if(getenv("CURL_FORBID_REUSE"))
|
if(getenv("CURL_FORBID_REUSE"))
|
||||||
(void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L);
|
(void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L);
|
||||||
|
if(getenv("CURL_FORBID_RETRY_ON_REUSE"))
|
||||||
|
(void)curl_easy_setopt(per->curl, CURLOPT_FORBID_RETRY_ON_REUSE, 1L);
|
||||||
|
|
||||||
if(global->test_duphandle) {
|
if(global->test_duphandle) {
|
||||||
CURL *dup = curl_easy_duphandle(per->curl);
|
CURL *dup = curl_easy_duphandle(per->curl);
|
||||||
|
|
|
@ -423,10 +423,13 @@ static CURLcode glob_parse(struct URLGlob *glob, const char *pattern,
|
||||||
if(++glob->size >= glob->palloc) {
|
if(++glob->size >= glob->palloc) {
|
||||||
struct URLPattern *np = NULL;
|
struct URLPattern *np = NULL;
|
||||||
glob->palloc *= 2;
|
glob->palloc *= 2;
|
||||||
if(glob->size < 10000) /* avoid ridiculous amounts */
|
if(glob->size < 255) { /* avoid ridiculous amounts */
|
||||||
np = realloc(glob->pattern, glob->palloc * sizeof(struct URLPattern));
|
np = realloc(glob->pattern, glob->palloc * sizeof(struct URLPattern));
|
||||||
if(!np)
|
if(!np)
|
||||||
return globerror(glob, NULL, pos, CURLE_OUT_OF_MEMORY);
|
return globerror(glob, NULL, pos, CURLE_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return globerror(glob, "too many {} sets", pos, CURLE_URL_MALFORMAT);
|
||||||
glob->pattern = np;
|
glob->pattern = np;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ test718 test719 test720 test721 test722 test723 test724 test725 test726 \
|
||||||
test727 test728 test729 test730 test731 test732 test733 test734 test735 \
|
test727 test728 test729 test730 test731 test732 test733 test734 test735 \
|
||||||
test736 test737 test738 test739 test740 test741 test742 test743 test744 \
|
test736 test737 test738 test739 test740 test741 test742 test743 test744 \
|
||||||
test745 test746 test747 test748 test749 test750 test751 test752 test753 \
|
test745 test746 test747 test748 test749 test750 test751 test752 test753 \
|
||||||
test754 test755 test756 test757 test758 test759 test760 \
|
test754 test755 test756 test757 test758 test759 test760 test761 \
|
||||||
test780 test781 test782 test783 test784 test785 test786 test787 test788 \
|
test780 test781 test782 test783 test784 test785 test786 test787 test788 \
|
||||||
test789 test790 test791 test792 test793 test794 test795 test796 test797 \
|
test789 test790 test791 test792 test793 test794 test795 test796 test797 \
|
||||||
\
|
\
|
||||||
|
|
33
tests/data/test761
Normal file
33
tests/data/test761
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
globbing
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
none
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
too many {} globs
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
http://testingthis/{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<errorcode>
|
||||||
|
3
|
||||||
|
</errorcode>
|
||||||
|
<stderr mode="text">
|
||||||
|
curl: (3) too many {} sets in URL position 403:
|
||||||
|
http://testingthis/{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a}b{a
|
||||||
|
</stderr>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
Loading…
Reference in New Issue
Block a user