Skip to content

Commit 3b9a09d

Browse files
committed
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.
1 parent 990f339 commit 3b9a09d

4 files changed

Lines changed: 29 additions & 8 deletions

File tree

ext/libsolvext.ver

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ SOLV_1.0 {
5555
rpm_stat_database;
5656
rpm_state_create;
5757
rpm_state_free;
58+
solv_fmemopen;
5859
solv_verify_sig;
5960
solv_xfopen;
6061
solv_xfopen_buf;

ext/solv_xfopen.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ struct bufcookie {
798798
size_t *buflp;
799799
char *freemem;
800800
size_t bufl_int;
801+
char *buf_int;
801802
};
802803

803804
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)
870871
return fp;
871872
}
872873

874+
FILE *
875+
solv_fmemopen(const char *buf, size_t bufl, const char *mode)
876+
{
877+
struct bufcookie *bc;
878+
FILE *fp;
879+
if (*mode != 'r')
880+
return 0;
881+
bc = solv_calloc(1, sizeof(*bc));
882+
bc->buf_int = (char *)buf;
883+
bc->bufl_int = bufl;
884+
bc->bufp = &bc->buf_int;
885+
bc->buflp = &bc->bufl_int;
886+
fp = cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose);
887+
if (!strcmp(mode, "rf")) /* auto-free */
888+
bc->freemem = bc->buf_int;
889+
if (!fp)
890+
cookie_bufclose(bc);
891+
return fp;
892+
}
893+
873894
#else
874895

875896
FILE *
876-
solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode)
897+
solv_fmemopen(const char *buf, size_t bufl, const char *mode)
877898
{
878899
FILE *fp;
879-
size_t l;
880900
if (*mode != 'r')
881901
return 0;
882-
l = buflp ? *buflp : strlen(*bufp);
883902
if (!strcmp(mode, "rf"))
884903
{
885-
if (!(fp = fmemopen(0, l, "r+")))
904+
if (!(fp = fmemopen(0, bufl, "r+")))
886905
return 0;
887-
if (l && fwrite(*bufp, l, 1, fp) != 1)
906+
if (bufl && fwrite(buf, bufl, 1, fp) != 1)
888907
{
889908
fclose(fp);
890909
return 0;
891910
}
892-
solv_free(*bufp);
911+
solv_free((char *)buf);
893912
rewind(fp);
894913
}
895914
else
896-
fp = fmemopen(*bufp, l, "r");
915+
fp = fmemopen((char *)buf, bufl, "r");
897916
return fp;
898917
}
899918

ext/solv_xfopen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ extern FILE *solv_xfopen(const char *fn, const char *mode);
1212
extern FILE *solv_xfopen_fd(const char *fn, int fd, const char *mode);
1313
extern FILE *solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode);
1414
extern int solv_xfopen_iscompressed(const char *fn);
15+
extern FILE *solv_fmemopen(const char *buf, size_t bufl, const char *mode);
1516

1617
#endif

ext/testcase.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2071,7 +2071,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
20712071
{
20722072
char *idata = read_inline_file(fp, &buf, &bufp, &bufl);
20732073
rdata = "<inline>";
2074-
rfp = solv_xfopen_buf(rdata, &idata, 0, "rf");
2074+
rfp = solv_fmemopen(idata, strlen(idata), "rf");
20752075
}
20762076
else
20772077
{

0 commit comments

Comments
 (0)