curl/tests/unit/unit3227.c
2026-07-13 08:29:22 +02:00

133 lines
4.5 KiB
C

/***************************************************************************
* _ _ ____ _
* 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 "unitcheck.h"
#include "urldata.h"
#include "mime.h"
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
!defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP))
/* does any generated part header carry a raw CR or LF, i.e. a split line? */
static bool headers_have_ctrl(const curl_mimepart *part)
{
const struct curl_slist *h;
for(h = part->curlheaders; h; h = h->next)
if(h->data[strcspn(h->data, "\r\n")])
return TRUE;
return FALSE;
}
static CURLcode t3227_setup(void)
{
CURLcode result = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
return result;
}
static void t3227_stop(CURL *easy, curl_mime *mime)
{
curl_mime_free(mime);
if(easy)
curl_easy_cleanup(easy);
curl_global_cleanup();
}
static CURLcode test_unit3227(const char *arg)
{
CURL *easy = NULL;
curl_mime *mime = NULL;
curl_mimepart *part;
UNITTEST_BEGIN(t3227_setup())
easy = curl_easy_init();
abort_unless(easy, "curl_easy_init()");
mime = curl_mime_init(easy);
abort_unless(mime, "curl_mime_init()");
/* A CR or LF in the mail-part name or filename would split the generated
Content-Disposition header. The mail strategy must reject it. */
part = curl_mime_addpart(mime);
abort_unless(part, "curl_mime_addpart()");
curl_mime_data(part, "x", 1);
curl_mime_filename(part, "a\r\nX-Injected: 1");
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
MIMESTRATEGY_MAIL) ==
CURLE_BAD_FUNCTION_ARGUMENT,
"CRLF filename accepted for mail");
part = curl_mime_addpart(mime);
abort_unless(part, "curl_mime_addpart()");
curl_mime_data(part, "x", 1);
curl_mime_name(part, "a\nb");
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
MIMESTRATEGY_MAIL) ==
CURLE_BAD_FUNCTION_ARGUMENT,
"LF name accepted for mail");
part = curl_mime_addpart(mime);
abort_unless(part, "curl_mime_addpart()");
curl_mime_data(part, "x", 1);
curl_mime_filename(part, "a\rb");
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
MIMESTRATEGY_MAIL) ==
CURLE_BAD_FUNCTION_ARGUMENT,
"CR filename accepted for mail");
/* A regular name and filename are accepted and produce a clean header. */
part = curl_mime_addpart(mime);
abort_unless(part, "curl_mime_addpart()");
curl_mime_data(part, "x", 1);
curl_mime_name(part, "field");
curl_mime_filename(part, "readme.txt");
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
MIMESTRATEGY_MAIL) == CURLE_OK,
"plain mail part rejected");
fail_if(headers_have_ctrl(part), "clean mail header split");
/* The HTTP form strategy percent-encodes CR/LF, so it stays accepted and
produces no split line. */
part = curl_mime_addpart(mime);
abort_unless(part, "curl_mime_addpart()");
curl_mime_data(part, "x", 1);
curl_mime_filename(part, "a\r\nX-Injected: 1");
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
MIMESTRATEGY_FORM) == CURLE_OK,
"CRLF filename rejected for form");
fail_if(headers_have_ctrl(part), "form header split despite encoding");
UNITTEST_END(t3227_stop(easy, mime))
}
#else /* mime disabled */
static CURLcode test_unit3227(const char *arg)
{
UNITTEST_BEGIN_SIMPLE
puts("nothing to do when mime is disabled");
UNITTEST_END_SIMPLE
}
#endif