test766: verify CURLOPT_SOCKOPTFUNCTION error on accept

This test does active FTP with a socketopt callback that returns error
for the CURLSOCKTYPE_ACCEPT "purpose" to make sure we test and exercise
this error path - without leaks.

Closes #18879
This commit is contained in:
Daniel Stenberg 2025-10-06 12:43:40 +02:00
parent 3517053cf7
commit 66f4c5699e
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 134 additions and 7 deletions

View file

@ -64,12 +64,14 @@ CURLOPT_SOCKOPTDATA(3) function.
Return *CURL_SOCKOPT_OK* from the callback on success. Return
*CURL_SOCKOPT_ERROR* from the callback function to signal an unrecoverable
error to the library and it closes the socket and returns
*CURLE_COULDNT_CONNECT*. Alternatively, the callback function can return
*CURL_SOCKOPT_ALREADY_CONNECTED*, to tell libcurl that the socket is
already connected and then libcurl does no attempt to connect. This allows an
application to pass in an already connected socket with
CURLOPT_OPENSOCKETFUNCTION(3) and then have this function make libcurl
not attempt to connect (again).
*CURLE_COULDNT_CONNECT* for *CURLSOCKTYPE_IPCXN* and
*CURLE_ABORTED_BY_CALLBACK* for *CURLSOCKTYPE_ACCEPT*.
The callback function may return *CURL_SOCKOPT_ALREADY_CONNECTED* for
*CURLSOCKTYPE_IPCXN*, to tell libcurl that the socket is already connected and
then libcurl does no attempt to connect. This allows an application to pass in
an already connected socket with CURLOPT_OPENSOCKETFUNCTION(3) and then have
this function make libcurl not attempt to connect (again).
# DEFAULT

View file

@ -109,7 +109,7 @@ test727 test728 test729 test730 test731 test732 test733 test734 test735 \
test736 test737 test738 test739 test740 test741 test742 test743 test744 \
test745 test746 test747 test748 test749 test750 test751 test752 test753 \
test754 test755 test756 test757 test758 test759 test760 test761 test762 \
test763 test764 test765 \
test763 test764 test765 test766 \
\
test780 test781 test782 test783 test784 test785 test786 test787 test788 \
test789 test790 test791 test792 test793 test794 test796 test797 \

58
tests/data/test766 Normal file
View file

@ -0,0 +1,58 @@
<testcase>
<info>
<keywords>
FTP
PORT
CURLOPT_SOCKOPTFUNCTION
</keywords>
</info>
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<tool>
lib%TESTNUMBER
</tool>
<name>
FTP PORT with sockopt callback refusing the accept
</name>
<command>
ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER
</command>
</client>
# Verify data after the test has been "shot"
<verify>
# Strip off parts of the EPRT command that might differ
<strippart>
s/^EPRT \|1\|(.*)/EPRT \|1\|/
</strippart>
# The TYPE command might get sent so we ignore that
<strip>
^TYPE
</strip>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
CWD path
EPRT |1|
</protocol>
# 42 == CURLE_ABORTED_BY_CALLBACK
<errorcode>
42
</errorcode>
</verify>
</testcase>

View file

@ -76,6 +76,7 @@ TESTS_C = \
lib694.c lib695.c \
lib751.c lib753.c lib758.c \
lib757.c \
lib766.c \
lib1156.c \
lib1301.c lib1308.c \
lib1485.c \

66
tests/libtest/lib766.c Normal file
View file

@ -0,0 +1,66 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 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
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "first.h"
#include "memdebug.h"
static int sockopt_766(void *clientp,
curl_socket_t curlfd,
curlsocktype purpose)
{
(void)clientp;
(void)curlfd;
if(purpose == CURLSOCKTYPE_ACCEPT) {
curl_mfprintf(stderr,
"Return error from CURLOPT_SOCKOPTFUNCTION callback\n");
return 1; /* force error */
}
return 0;
}
static CURLcode test_lib766(const char *URL)
{
CURL *easy = NULL;
CURLcode res = CURLE_OK;
start_test_timing();
res_global_init(CURL_GLOBAL_ALL);
easy_init(easy);
easy_setopt(easy, CURLOPT_VERBOSE, 1L);
easy_setopt(easy, CURLOPT_URL, URL);
easy_setopt(easy, CURLOPT_FTPPORT, "-");
easy_setopt(easy, CURLOPT_SOCKOPTFUNCTION, sockopt_766);
res = curl_easy_perform(easy);
test_cleanup:
curl_easy_cleanup(easy);
curl_global_cleanup();
return res;
}