1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. |
9 | * |
10 | * This software is licensed as described in the file COPYING, which |
11 | * you should have received as part of this distribution. The terms |
12 | * are also available at https://curl.haxx.se/docs/copyright.html. |
13 | * |
14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
15 | * copies of the Software, and permit persons to whom the Software is |
16 | * furnished to do so, under the terms of the COPYING file. |
17 | * |
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
19 | * KIND, either express or implied. |
20 | * |
21 | ***************************************************************************/ |
22 | #include "test.h" |
23 | |
24 | #include "memdebug.h" |
25 | |
26 | static char data[]= |
27 | #ifdef CURL_DOES_CONVERSIONS |
28 | /* ASCII representation with escape sequences for non-ASCII platforms */ |
29 | "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70" |
30 | "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20" |
31 | "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72\x0a" ; |
32 | #else |
33 | "this is what we post to the silly web server\n" ; |
34 | #endif |
35 | |
36 | struct WriteThis { |
37 | char *readptr; |
38 | curl_off_t sizeleft; |
39 | int freecount; |
40 | }; |
41 | |
42 | static void free_callback(void *userp) |
43 | { |
44 | struct WriteThis *pooh = (struct WriteThis *) userp; |
45 | |
46 | pooh->freecount++; |
47 | } |
48 | |
49 | static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) |
50 | { |
51 | struct WriteThis *pooh = (struct WriteThis *)userp; |
52 | int eof = !*pooh->readptr; |
53 | |
54 | if(size*nmemb < 1) |
55 | return 0; |
56 | |
57 | eof = pooh->sizeleft <= 0; |
58 | if(!eof) |
59 | pooh->sizeleft--; |
60 | |
61 | if(!eof) { |
62 | *ptr = *pooh->readptr; /* copy one single byte */ |
63 | pooh->readptr++; /* advance pointer */ |
64 | return 1; /* we return 1 byte at a time! */ |
65 | } |
66 | |
67 | return 0; /* no more data left to deliver */ |
68 | } |
69 | |
70 | int test(char *URL) |
71 | { |
72 | CURL *easy = NULL; |
73 | CURL *easy2 = NULL; |
74 | curl_mime *mime = NULL; |
75 | curl_mimepart *part; |
76 | struct curl_slist *hdrs = NULL; |
77 | CURLcode result; |
78 | int res = TEST_ERR_FAILURE; |
79 | struct WriteThis pooh; |
80 | |
81 | /* |
82 | * Check proper copy/release of mime post data bound to a duplicated |
83 | * easy handle. |
84 | */ |
85 | |
86 | if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { |
87 | fprintf(stderr, "curl_global_init() failed\n" ); |
88 | return TEST_ERR_MAJOR_BAD; |
89 | } |
90 | |
91 | easy = curl_easy_init(); |
92 | |
93 | /* First set the URL that is about to receive our POST. */ |
94 | test_setopt(easy, CURLOPT_URL, URL); |
95 | |
96 | /* get verbose debug output please */ |
97 | test_setopt(easy, CURLOPT_VERBOSE, 1L); |
98 | |
99 | /* include headers in the output */ |
100 | test_setopt(easy, CURLOPT_HEADER, 1L); |
101 | |
102 | /* Prepare the callback structure. */ |
103 | pooh.readptr = data; |
104 | pooh.sizeleft = (curl_off_t) strlen(data); |
105 | pooh.freecount = 0; |
106 | |
107 | /* Build the mime tree. */ |
108 | mime = curl_mime_init(easy); |
109 | part = curl_mime_addpart(mime); |
110 | curl_mime_data(part, "hello" , CURL_ZERO_TERMINATED); |
111 | curl_mime_name(part, "greeting" ); |
112 | curl_mime_type(part, "application/X-Greeting" ); |
113 | curl_mime_encoder(part, "base64" ); |
114 | hdrs = curl_slist_append(hdrs, "X-Test-Number: 654" ); |
115 | curl_mime_headers(part, hdrs, TRUE); |
116 | part = curl_mime_addpart(mime); |
117 | curl_mime_filedata(part, "log/file654.txt" ); |
118 | part = curl_mime_addpart(mime); |
119 | curl_mime_data_cb(part, (curl_off_t) -1, read_callback, NULL, free_callback, |
120 | &pooh); |
121 | |
122 | /* Bind mime data to its easy handle. */ |
123 | test_setopt(easy, CURLOPT_MIMEPOST, mime); |
124 | |
125 | /* Duplicate the handle. */ |
126 | easy2 = curl_easy_duphandle(easy); |
127 | if(!easy2) { |
128 | fprintf(stderr, "curl_easy_duphandle() failed\n" ); |
129 | res = TEST_ERR_FAILURE; |
130 | goto test_cleanup; |
131 | } |
132 | |
133 | /* Now free the mime structure: it should unbind it from the first |
134 | easy handle. */ |
135 | curl_mime_free(mime); |
136 | mime = NULL; /* Already cleaned up. */ |
137 | |
138 | /* Perform on the first handle: should not send any data. */ |
139 | result = curl_easy_perform(easy); |
140 | if(result) { |
141 | fprintf(stderr, "curl_easy_perform(original) failed\n" ); |
142 | res = (int) result; |
143 | goto test_cleanup; |
144 | } |
145 | |
146 | /* Perform on the second handle: if the bound mime structure has not been |
147 | duplicated properly, it should cause a valgrind error. */ |
148 | result = curl_easy_perform(easy2); |
149 | if(result) { |
150 | fprintf(stderr, "curl_easy_perform(duplicated) failed\n" ); |
151 | res = (int) result; |
152 | goto test_cleanup; |
153 | } |
154 | |
155 | /* Free the duplicated handle: it should call free_callback again. |
156 | If the mime copy was bad or not automatically released, valgrind |
157 | will signal it. */ |
158 | curl_easy_cleanup(easy2); |
159 | easy2 = NULL; /* Already cleaned up. */ |
160 | |
161 | if(pooh.freecount != 2) { |
162 | fprintf(stderr, "free_callback() called %d times instead of 2\n" , |
163 | pooh.freecount); |
164 | res = TEST_ERR_FAILURE; |
165 | goto test_cleanup; |
166 | } |
167 | |
168 | test_cleanup: |
169 | curl_easy_cleanup(easy); |
170 | curl_easy_cleanup(easy2); |
171 | curl_mime_free(mime); |
172 | curl_global_cleanup(); |
173 | return res; |
174 | } |
175 | |