/* Provenance: curl/curl cookie_output (fixed). * repo: curl/curl * commit: 20f9dd6bae50b7223171b17ba7798946e74f877f * parent: 46f8911d3942dc06fdd67e9f6f3908982e5d2fb4 * commit_url: https://github.com/curl/curl/commit/20f9dd6bae50b7223171b17ba7798946e74f877f * cve: CVE-2022-32207 * license: curl * function: cookie_output * relpath: lib/cookie.c * provenance: human * mechanism: other */ static CURLcode cookie_output(struct Curl_easy *data, struct CookieInfo *c, const char *filename) { struct Cookie *co; FILE *out = NULL; bool use_stdout = FALSE; char *tempstore = NULL; CURLcode error = CURLE_OK; if(!c) /* no cookie engine alive */ return CURLE_OK; /* at first, remove expired cookies */ remove_expired(c); if(!strcmp("-", filename)) { /* use stdout */ out = stdout; use_stdout = TRUE; } else { error = Curl_fopen(data, filename, &out, &tempstore); if(error) goto error; } fputs("# Netscape HTTP Cookie File\n" "# https://curl.se/docs/http-cookies.html\n" "# This file was generated by libcurl! Edit at your own risk.\n\n", out); if(c->numcookies) { unsigned int i; size_t nvalid = 0; struct Cookie **array; array = calloc(1, sizeof(struct Cookie *) * c->numcookies); if(!array) { error = CURLE_OUT_OF_MEMORY; goto error; } /* only sort the cookies with a domain property */ for(i = 0; i < COOKIE_HASH_SIZE; i++) { for(co = c->cookies[i]; co; co = co->next) { if(!co->domain) continue; array[nvalid++] = co; } } qsort(array, nvalid, sizeof(struct Cookie *), cookie_sort_ct); for(i = 0; i < nvalid; i++) { char *format_ptr = get_netscape_format(array[i]); if(!format_ptr) { free(array); error = CURLE_OUT_OF_MEMORY; goto error; } fprintf(out, "%s\n", format_ptr); free(format_ptr); } free(array); } if(!use_stdout) { fclose(out); out = NULL; if(tempstore && Curl_rename(tempstore, filename)) { unlink(tempstore); error = CURLE_WRITE_ERROR; goto error; } } /* * If we reach here we have successfully written a cookie file so theree is * no need to inspect the error, any error case should have jumped into the * error block below. */ free(tempstore); return CURLE_OK; error: if(out && !use_stdout) fclose(out); free(tempstore); return error; }