libpwdgrp: fix a memory leak in getXXnam (we did not save address of string buf)
function old new delta convert_to_struct 261 269 +8 const_sp_db 20 24 +4 const_pw_db 20 24 +4 const_gr_db 20 24 +4 tokenize 144 147 +3 parse_common 185 188 +3 get_S 82 85 +3 bb_internal_getpwent_r 188 185 -3 gr_off 4 - -4 getXXnam 171 165 -6 pw_off 7 - -7 getgrouplist_internal 237 229 -8 getXXnam_r 215 207 -8 sp_off 9 - -9 ------------------------------------------------------------------------------ (add/remove: 0/3 grow/shrink: 7/4 up/down: 29/-45) Total: -16 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
31d6734457
commit
8d547aca75
@ -32,6 +32,27 @@
|
|||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
|
struct const_passdb {
|
||||||
|
const char *filename;
|
||||||
|
const char def[10];
|
||||||
|
const uint8_t off[9];
|
||||||
|
uint8_t numfields;
|
||||||
|
};
|
||||||
|
struct passdb {
|
||||||
|
const char *filename;
|
||||||
|
const char def[10];
|
||||||
|
const uint8_t off[9];
|
||||||
|
uint8_t numfields;
|
||||||
|
FILE *fp;
|
||||||
|
char *malloced;
|
||||||
|
char struct_result[0
|
||||||
|
| sizeof(struct passwd)
|
||||||
|
| sizeof(struct group)
|
||||||
|
IF_USE_BB_SHADOW( | sizeof(struct spwd) )
|
||||||
|
/* bitwise OR above is poor man's max(a,b,c) */
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
/* S = string not empty, s = string maybe empty,
|
/* S = string not empty, s = string maybe empty,
|
||||||
* I = uid,gid, l = long maybe empty, m = members,
|
* I = uid,gid, l = long maybe empty, m = members,
|
||||||
* r = reserved
|
* r = reserved
|
||||||
@ -40,61 +61,50 @@
|
|||||||
#define GR_DEF "SsIm"
|
#define GR_DEF "SsIm"
|
||||||
#define SP_DEF "Ssllllllr"
|
#define SP_DEF "Ssllllllr"
|
||||||
|
|
||||||
static const uint8_t pw_off[] ALIGN1 = {
|
static const struct const_passdb const_pw_db = {
|
||||||
offsetof(struct passwd, pw_name), /* 0 S */
|
_PATH_PASSWD, PW_DEF,
|
||||||
offsetof(struct passwd, pw_passwd), /* 1 s */
|
{
|
||||||
offsetof(struct passwd, pw_uid), /* 2 I */
|
offsetof(struct passwd, pw_name), /* 0 S */
|
||||||
offsetof(struct passwd, pw_gid), /* 3 I */
|
offsetof(struct passwd, pw_passwd), /* 1 s */
|
||||||
offsetof(struct passwd, pw_gecos), /* 4 s */
|
offsetof(struct passwd, pw_uid), /* 2 I */
|
||||||
offsetof(struct passwd, pw_dir), /* 5 S */
|
offsetof(struct passwd, pw_gid), /* 3 I */
|
||||||
offsetof(struct passwd, pw_shell) /* 6 S */
|
offsetof(struct passwd, pw_gecos), /* 4 s */
|
||||||
|
offsetof(struct passwd, pw_dir), /* 5 S */
|
||||||
|
offsetof(struct passwd, pw_shell) /* 6 S */
|
||||||
|
},
|
||||||
|
sizeof(PW_DEF)-1
|
||||||
};
|
};
|
||||||
static const uint8_t gr_off[] ALIGN1 = {
|
static const struct const_passdb const_gr_db = {
|
||||||
offsetof(struct group, gr_name), /* 0 S */
|
_PATH_GROUP, GR_DEF,
|
||||||
offsetof(struct group, gr_passwd), /* 1 s */
|
{
|
||||||
offsetof(struct group, gr_gid), /* 2 I */
|
offsetof(struct group, gr_name), /* 0 S */
|
||||||
offsetof(struct group, gr_mem) /* 3 m (char **) */
|
offsetof(struct group, gr_passwd), /* 1 s */
|
||||||
|
offsetof(struct group, gr_gid), /* 2 I */
|
||||||
|
offsetof(struct group, gr_mem) /* 3 m (char **) */
|
||||||
|
},
|
||||||
|
sizeof(GR_DEF)-1
|
||||||
};
|
};
|
||||||
#if ENABLE_USE_BB_SHADOW
|
#if ENABLE_USE_BB_SHADOW
|
||||||
static const uint8_t sp_off[] ALIGN1 = {
|
static const struct const_passdb const_sp_db = {
|
||||||
offsetof(struct spwd, sp_namp), /* 0 S Login name */
|
_PATH_SHADOW, SP_DEF,
|
||||||
offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */
|
{
|
||||||
offsetof(struct spwd, sp_lstchg), /* 2 l */
|
offsetof(struct spwd, sp_namp), /* 0 S Login name */
|
||||||
offsetof(struct spwd, sp_min), /* 3 l */
|
offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */
|
||||||
offsetof(struct spwd, sp_max), /* 4 l */
|
offsetof(struct spwd, sp_lstchg), /* 2 l */
|
||||||
offsetof(struct spwd, sp_warn), /* 5 l */
|
offsetof(struct spwd, sp_min), /* 3 l */
|
||||||
offsetof(struct spwd, sp_inact), /* 6 l */
|
offsetof(struct spwd, sp_max), /* 4 l */
|
||||||
offsetof(struct spwd, sp_expire), /* 7 l */
|
offsetof(struct spwd, sp_warn), /* 5 l */
|
||||||
offsetof(struct spwd, sp_flag) /* 8 r Reserved */
|
offsetof(struct spwd, sp_inact), /* 6 l */
|
||||||
|
offsetof(struct spwd, sp_expire), /* 7 l */
|
||||||
|
offsetof(struct spwd, sp_flag) /* 8 r Reserved */
|
||||||
|
},
|
||||||
|
sizeof(SP_DEF)-1
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct const_passdb {
|
|
||||||
const char *filename;
|
|
||||||
const uint8_t *off;
|
|
||||||
const char def[10];
|
|
||||||
uint8_t numfields;
|
|
||||||
uint8_t size_of;
|
|
||||||
};
|
|
||||||
struct passdb {
|
|
||||||
const char *filename;
|
|
||||||
const uint8_t *off;
|
|
||||||
const char def[10];
|
|
||||||
uint8_t numfields;
|
|
||||||
uint8_t size_of;
|
|
||||||
FILE *fp;
|
|
||||||
void *malloced;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct const_passdb const_pw_db = { _PATH_PASSWD, pw_off, PW_DEF, sizeof(PW_DEF)-1, sizeof(struct passwd) };
|
|
||||||
static const struct const_passdb const_gr_db = { _PATH_GROUP , gr_off, GR_DEF, sizeof(GR_DEF)-1, sizeof(struct group) };
|
|
||||||
#if ENABLE_USE_BB_SHADOW
|
|
||||||
static const struct const_passdb const_sp_db = { _PATH_SHADOW, sp_off, SP_DEF, sizeof(SP_DEF)-1, sizeof(struct spwd) };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We avoid having big global data. */
|
/* We avoid having big global data. */
|
||||||
struct statics {
|
struct statics {
|
||||||
/* It's ok to use same buffer (db[0].malloced) for getpwuid and getpwnam.
|
/* It's ok to use same buffer (db[0].struct_result) for getpwuid and getpwnam.
|
||||||
* Manpage says:
|
* Manpage says:
|
||||||
* "The return value may point to a static area, and may be overwritten
|
* "The return value may point to a static area, and may be overwritten
|
||||||
* by subsequent calls to getpwent(), getpwnam(), or getpwuid()."
|
* by subsequent calls to getpwent(), getpwnam(), or getpwuid()."
|
||||||
@ -223,9 +233,15 @@ static char *parse_file(const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Convert passwd/group/shadow file record in buffer to a struct */
|
/* Convert passwd/group/shadow file record in buffer to a struct */
|
||||||
static void *convert_to_struct(const char *def, const unsigned char *off,
|
static void *convert_to_struct(struct passdb *db,
|
||||||
char *buffer, void *result)
|
char *buffer, void *result)
|
||||||
{
|
{
|
||||||
|
const char *def = db->def;
|
||||||
|
const uint8_t *off = db->off;
|
||||||
|
|
||||||
|
/* TODO? for consistency, zero out all fields */
|
||||||
|
/* memset(result, 0, size_of_result);*/
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
void *member = (char*)result + (*off++);
|
void *member = (char*)result + (*off++);
|
||||||
|
|
||||||
@ -282,7 +298,8 @@ static void *convert_to_struct(const char *def, const unsigned char *off,
|
|||||||
|
|
||||||
/****** getXXnam/id_r */
|
/****** getXXnam/id_r */
|
||||||
|
|
||||||
static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer, size_t buflen,
|
static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
void *result)
|
void *result)
|
||||||
{
|
{
|
||||||
void *struct_buf = *(void**)result;
|
void *struct_buf = *(void**)result;
|
||||||
@ -299,7 +316,7 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, ch
|
|||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
} else {
|
} else {
|
||||||
memcpy(buffer, buf, size);
|
memcpy(buffer, buf, size);
|
||||||
*(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf);
|
*(void**)result = convert_to_struct(db, buffer, struct_buf);
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
@ -310,8 +327,9 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, ch
|
|||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen,
|
int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf,
|
||||||
struct passwd **result)
|
char *buffer, size_t buflen,
|
||||||
|
struct passwd **result)
|
||||||
{
|
{
|
||||||
/* Why the "store buffer address in result" trick?
|
/* Why the "store buffer address in result" trick?
|
||||||
* This way, getXXnam_r has the same ABI signature as getpwnam_r,
|
* This way, getXXnam_r has the same ABI signature as getpwnam_r,
|
||||||
@ -357,7 +375,7 @@ static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen,
|
|||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
} else {
|
} else {
|
||||||
memcpy(buffer, buf, size);
|
memcpy(buffer, buf, size);
|
||||||
*(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf);
|
*(void**)result = convert_to_struct(db, buffer, struct_buf);
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
@ -393,12 +411,11 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos)
|
|||||||
close_on_exec_on(fileno(db->fp));
|
close_on_exec_on(fileno(db->fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(db->malloced);
|
|
||||||
db->malloced = NULL;
|
|
||||||
buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3);
|
buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
db->malloced = xzalloc(db->size_of);
|
free(db->malloced);
|
||||||
result = convert_to_struct(db->def, db->off, buf, db->malloced);
|
db->malloced = buf;
|
||||||
|
result = convert_to_struct(db, buf, db->struct_result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -465,7 +482,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr,
|
|||||||
while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) {
|
while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) {
|
||||||
char **m;
|
char **m;
|
||||||
struct group group;
|
struct group group;
|
||||||
if (!convert_to_struct(GR_DEF, gr_off, buf, &group))
|
if (!convert_to_struct(&S.db[1], buf, &group))
|
||||||
goto next;
|
goto next;
|
||||||
if (group.gr_gid == gid)
|
if (group.gr_gid == gid)
|
||||||
goto next;
|
goto next;
|
||||||
|
Loading…
Reference in New Issue
Block a user