If the full hostname doesn't fit in the buffer supplied to gethostname, POSIX does not specify whether the buffer will be null-terminated, so to be safe, we should do it ourselves. Introduce new function, xgethostname, which ensures that there is always a \0 at the end of the buffer. Always use a consistent buffer size when calling xgethostname. We use HOST_NAME_MAX + 1. When this is unavailable, we fall back to 256, a decision we previously made in daemon.c, but which we now move to git-compat-util.h so that it can be used everywhere. Signed-off-by: David Turner <dturner@xxxxxxxxxxxx> --- This version addresses some comments by René Scharfe. René, we're still silently truncating, but as I noted in my message to Jonathan: Looking at the users of this function, I think most would be happier with a truncated buffer than an error: * gc.c: used to see if we are the same machine as the machine that locked the repo. it is unlikely that two machines have hostnames that differ only in the 256th-or-above character, and it would be weird to fail to gc just because our hostname is long. * fetch-pack.c, receive-pack.c: similar to gc.c; the hostname is a note in the .keep file for human consumption only * ident.c: used to make up a fake email address. On my laptop, gethostname returns "corey" (no domain part), so the email address is not likely to be valid anyway. builtin/gc.c | 6 +++--- builtin/receive-pack.c | 4 ++-- daemon.c | 4 ---- fetch-pack.c | 4 ++-- git-compat-util.h | 6 ++++++ ident.c | 4 ++-- wrapper.c | 13 +++++++++++++ 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/builtin/gc.c b/builtin/gc.c index c2c61a57bb..5de0209c59 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -238,7 +238,7 @@ static int need_to_gc(void) static const char *lock_repo_for_gc(int force, pid_t* ret_pid) { static struct lock_file lock; - char my_host[128]; + char my_host[HOST_NAME_MAX + 1]; struct strbuf sb = STRBUF_INIT; struct stat st; uintmax_t pid; @@ -250,14 +250,14 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) /* already locked */ return NULL; - if (gethostname(my_host, sizeof(my_host))) + if (xgethostname(my_host, sizeof(my_host))) xsnprintf(my_host, sizeof(my_host), "unknown"); pidfile_path = git_pathdup("gc.pid"); fd = hold_lock_file_for_update(&lock, pidfile_path, LOCK_DIE_ON_ERROR); if (!force) { - static char locking_host[128]; + static char locking_host[HOST_NAME_MAX + 1]; int should_exit; fp = fopen(pidfile_path, "r"); memset(locking_host, 0, sizeof(locking_host)); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index aca9c33d8d..0ca423a711 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1695,12 +1695,12 @@ static const char *unpack(int err_fd, struct shallow_info *si) if (status) return "unpack-objects abnormal exit"; } else { - char hostname[256]; + char hostname[HOST_NAME_MAX + 1]; argv_array_pushl(&child.args, "index-pack", "--stdin", hdr_arg, NULL); - if (gethostname(hostname, sizeof(hostname))) + if (xgethostname(hostname, sizeof(hostname))) xsnprintf(hostname, sizeof(hostname), "localhost"); argv_array_pushf(&child.args, "--keep=receive-pack %"PRIuMAX" on %s", diff --git a/daemon.c b/daemon.c index 473e6b6b63..1503e1ed6f 100644 --- a/daemon.c +++ b/daemon.c @@ -4,10 +4,6 @@ #include "strbuf.h" #include "string-list.h" -#ifndef HOST_NAME_MAX -#define HOST_NAME_MAX 256 -#endif - #ifdef NO_INITGROUPS #define initgroups(x, y) (0) /* nothing */ #endif diff --git a/fetch-pack.c b/fetch-pack.c index d07d85ce30..15d59a0440 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -802,8 +802,8 @@ static int get_pack(struct fetch_pack_args *args, if (args->use_thin_pack) argv_array_push(&cmd.args, "--fix-thin"); if (args->lock_pack || unpack_limit) { - char hostname[256]; - if (gethostname(hostname, sizeof(hostname))) + char hostname[HOST_NAME_MAX + 1]; + if (xgethostname(hostname, sizeof(hostname))) xsnprintf(hostname, sizeof(hostname), "localhost"); argv_array_pushf(&cmd.args, "--keep=fetch-pack %"PRIuMAX " on %s", diff --git a/git-compat-util.h b/git-compat-util.h index 8a4a3f85e7..bd04564a69 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -884,6 +884,12 @@ static inline size_t xsize_t(off_t len) __attribute__((format (printf, 3, 4))) extern int xsnprintf(char *dst, size_t max, const char *fmt, ...); +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 256 +#endif + +extern int xgethostname(char *buf, size_t len); + /* in ctype.c, for kwset users */ extern const unsigned char tolower_trans_tbl[256]; diff --git a/ident.c b/ident.c index c0364fe3a1..bea871c8e0 100644 --- a/ident.c +++ b/ident.c @@ -120,9 +120,9 @@ static int canonical_name(const char *host, struct strbuf *out) static void add_domainname(struct strbuf *out, int *is_bogus) { - char buf[1024]; + char buf[HOST_NAME_MAX + 1]; - if (gethostname(buf, sizeof(buf))) { + if (xgethostname(buf, sizeof(buf))) { warning_errno("cannot get host name"); strbuf_addstr(out, "(none)"); *is_bogus = 1; diff --git a/wrapper.c b/wrapper.c index 0542fc7582..d837417709 100644 --- a/wrapper.c +++ b/wrapper.c @@ -655,3 +655,16 @@ void sleep_millisec(int millisec) { poll(NULL, 0, millisec); } + +int xgethostname(char *buf, size_t len) +{ + /* + * If the full hostname doesn't fit in buf, POSIX does not + * specify whether the buffer will be null-terminated, so to + * be safe, do it ourselves. + */ + int ret = gethostname(buf, len); + if (!ret) + buf[len - 1] = 0; + return ret; +} -- 2.11.GIT