aboutsummaryrefslogtreecommitdiff
path: root/src/tool_cb_wrt.c
diff options
context:
space:
mode:
authorYang Tse <yangsita@gmail.com>2011-09-30 20:56:56 +0200
committerYang Tse <yangsita@gmail.com>2011-09-30 21:10:58 +0200
commit7be872c389a4cc97a4594912d1e0bdd865974780 (patch)
treedfec3268260596d189ad5f60721e3c4a727fae81 /src/tool_cb_wrt.c
parent0c903ea18962ef51984733afc28f4f811c4788c5 (diff)
curl tool: fix some more OOM handling
Diffstat (limited to 'src/tool_cb_wrt.c')
-rw-r--r--src/tool_cb_wrt.c86
1 files changed, 61 insertions, 25 deletions
diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c
index 1889080de..de94f6e49 100644
--- a/src/tool_cb_wrt.c
+++ b/src/tool_cb_wrt.c
@@ -40,8 +40,8 @@
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
{
size_t rc;
- struct OutStruct *out = userdata;
- struct Configurable *config = out->config;
+ struct OutStruct *outs = userdata;
+ struct Configurable *config = outs->config;
/*
* Once that libcurl has called back tool_write_cb() the returned value
@@ -49,47 +49,85 @@ size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
* point returning a value different from sz*nmemb indicates failure.
*/
- const size_t err_rc = (sz * nmemb) ? 0 : 1;
+ const size_t failure = (sz * nmemb) ? 0 : 1;
+
+ if(!config)
+ return failure;
#ifdef DEBUGBUILD
if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
warnf(config, "Data size exceeds single call write limit!\n");
- return err_rc; /* Failure */
+ return failure;
+ }
+
+ {
+ /* Some internal congruency checks on received OutStruct */
+ bool check_fails = FALSE;
+ if(outs->filename) {
+ /* regular file */
+ if(!*outs->filename)
+ check_fails = TRUE;
+ if(!outs->s_isreg)
+ check_fails = TRUE;
+ if(outs->fopened && !outs->stream)
+ check_fails = TRUE;
+ if(!outs->fopened && outs->stream)
+ check_fails = TRUE;
+ if(!outs->fopened && outs->bytes)
+ check_fails = TRUE;
+ }
+ else {
+ /* standard stream */
+ if(!outs->stream || outs->s_isreg || outs->fopened)
+ check_fails = TRUE;
+ if(outs->alloc_filename || outs->init)
+ check_fails = TRUE;
+ }
+ if(check_fails) {
+ warnf(config, "Invalid output struct data for write callback\n");
+ return failure;
+ }
}
#endif
- if(!out->stream) {
- out->bytes = 0; /* nothing written yet */
- if(!out->filename) {
+ if(!outs->stream) {
+ FILE *file;
+
+ if(!outs->filename || !*outs->filename) {
warnf(config, "Remote filename has no length!\n");
- return err_rc; /* Failure */
+ return failure;
}
if(config->content_disposition) {
/* don't overwrite existing files */
- FILE* f = fopen(out->filename, "r");
- if(f) {
- fclose(f);
- warnf(config, "Refusing to overwrite %s: %s\n", out->filename,
+ file = fopen(outs->filename, "rb");
+ if(file) {
+ fclose(file);
+ warnf(config, "Refusing to overwrite %s: %s\n", outs->filename,
strerror(EEXIST));
- return err_rc; /* Failure */
+ return failure;
}
}
/* open file for writing */
- out->stream = fopen(out->filename, "wb");
- if(!out->stream) {
- warnf(config, "Failed to create the file %s: %s\n", out->filename,
+ file = fopen(outs->filename, "wb");
+ if(!file) {
+ warnf(config, "Failed to create the file %s: %s\n", outs->filename,
strerror(errno));
- return err_rc; /* failure */
+ return failure;
}
+ outs->s_isreg = TRUE;
+ outs->fopened = TRUE;
+ outs->stream = file;
+ outs->bytes = 0;
+ outs->init = 0;
}
- rc = fwrite(buffer, sz, nmemb, out->stream);
+ rc = fwrite(buffer, sz, nmemb, outs->stream);
if((sz * nmemb) == rc)
/* we added this amount of data to the output */
- out->bytes += (sz * nmemb);
+ outs->bytes += (sz * nmemb);
if(config->readbusy) {
config->readbusy = FALSE;
@@ -97,12 +135,10 @@ size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
}
if(config->nobuffer) {
- /* disable output buffering */
- int res = fflush(out->stream);
- if(res) {
- /* return a value that isn't the same as sz * nmemb */
- return err_rc; /* failure */
- }
+ /* output buffering disabled */
+ int res = fflush(outs->stream);
+ if(res)
+ return failure;
}
return rc;