From: Michael Schroeder Date: Wed, 3 Jun 2020 12:06:32 +0000 (+0200) Subject: Add solv_fmemopen() function X-Git-Tag: 0.7.15~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3b9a09d5729038a385bfd001c768ef84fe12397a;p=thirdparty%2Flibsolv.git Add solv_fmemopen() function The solv_xfopen_buf() function we have has the disadvantage that it updates the buffer pointer/length when reading/writing. This can easily lead to writing to locations that went out of scope, like with our usage in testcase.c. So solv_fmemopen() removes that indirection and directly takes the buffer pointer and length as arguments. Only reading is currently supported. --- diff --git a/ext/libsolvext.ver b/ext/libsolvext.ver index 64238378..5e9b0799 100644 --- a/ext/libsolvext.ver +++ b/ext/libsolvext.ver @@ -55,6 +55,7 @@ SOLV_1.0 { rpm_stat_database; rpm_state_create; rpm_state_free; + solv_fmemopen; solv_verify_sig; solv_xfopen; solv_xfopen_buf; diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c index 4bb4628c..7e974a91 100644 --- a/ext/solv_xfopen.c +++ b/ext/solv_xfopen.c @@ -798,6 +798,7 @@ struct bufcookie { size_t *buflp; char *freemem; size_t bufl_int; + char *buf_int; }; static ssize_t cookie_bufread(void *cookie, char *buf, size_t nbytes) @@ -870,30 +871,48 @@ solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode) return fp; } +FILE * +solv_fmemopen(const char *buf, size_t bufl, const char *mode) +{ + struct bufcookie *bc; + FILE *fp; + if (*mode != 'r') + return 0; + bc = solv_calloc(1, sizeof(*bc)); + bc->buf_int = (char *)buf; + bc->bufl_int = bufl; + bc->bufp = &bc->buf_int; + bc->buflp = &bc->bufl_int; + fp = cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose); + if (!strcmp(mode, "rf")) /* auto-free */ + bc->freemem = bc->buf_int; + if (!fp) + cookie_bufclose(bc); + return fp; +} + #else FILE * -solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode) +solv_fmemopen(const char *buf, size_t bufl, const char *mode) { FILE *fp; - size_t l; if (*mode != 'r') return 0; - l = buflp ? *buflp : strlen(*bufp); if (!strcmp(mode, "rf")) { - if (!(fp = fmemopen(0, l, "r+"))) + if (!(fp = fmemopen(0, bufl, "r+"))) return 0; - if (l && fwrite(*bufp, l, 1, fp) != 1) + if (bufl && fwrite(buf, bufl, 1, fp) != 1) { fclose(fp); return 0; } - solv_free(*bufp); + solv_free((char *)buf); rewind(fp); } else - fp = fmemopen(*bufp, l, "r"); + fp = fmemopen((char *)buf, bufl, "r"); return fp; } diff --git a/ext/solv_xfopen.h b/ext/solv_xfopen.h index aa8740e8..613f3317 100644 --- a/ext/solv_xfopen.h +++ b/ext/solv_xfopen.h @@ -12,5 +12,6 @@ extern FILE *solv_xfopen(const char *fn, const char *mode); extern FILE *solv_xfopen_fd(const char *fn, int fd, const char *mode); extern FILE *solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode); extern int solv_xfopen_iscompressed(const char *fn); +extern FILE *solv_fmemopen(const char *buf, size_t bufl, const char *mode); #endif diff --git a/ext/testcase.c b/ext/testcase.c index d6c4a577..16727068 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -2071,7 +2071,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res { char *idata = read_inline_file(fp, &buf, &bufp, &bufl); rdata = ""; - rfp = solv_xfopen_buf(rdata, &idata, 0, "rf"); + rfp = solv_fmemopen(idata, strlen(idata), "rf"); } else {