#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
+#include <math.h>
#include <errno.h>
#include "launch.h"
struct launch_msg_header {
uint64_t magic;
+ uint64_t fdcnt;
uint64_t len;
};
static pthread_once_t _lc_once = PTHREAD_ONCE_INIT;
+void (*__log_liblaunch_bug)(const char *path, unsigned int line, const char *test) = NULL;
+
+static void
+_log_liblaunch_bug(const char *path, unsigned int line, const char *test)
+{
+ if (__log_liblaunch_bug)
+ __log_liblaunch_bug(path, line, test);
+}
+
+#define assumes(e) \
+ (__builtin_expect(!(e), 0) ? _log_liblaunch_bug(__FILE__, __LINE__, #e), false : true)
+
static struct _launch_client {
pthread_mutex_t mtx;
launch_t l;
if (_launchd_fd) {
lfd = strtol(_launchd_fd, NULL, 10);
if ((dfd = dup(lfd)) >= 0) {
- close(dfd);
+ assumes(close(dfd) != -1);
_fd(lfd);
} else {
lfd = -1;
else
snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%u/sock", LAUNCHD_SOCK_PREFIX, getuid());
- if ((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) == -1)
+ if (!assumes((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) != -1))
goto out_bad;
for (tries = 0; tries < 10; tries++) {
}
}
if (r == -1) {
- close(lfd);
+ assumes(close(lfd) != -1);
goto out_bad;
}
}
size_t launch_data_dict_get_count(launch_data_t dict)
{
+ if (!assumes(dict->type == LAUNCH_DATA_DICTIONARY))
+ return 0;
+
return dict->_array_cnt / 2;
}
bool launch_data_dict_insert(launch_data_t dict, launch_data_t what, const char *key)
{
+ launch_data_t thekey;
size_t i;
- launch_data_t thekey = launch_data_alloc(LAUNCH_DATA_STRING);
- launch_data_set_string(thekey, key);
+ if (!assumes(dict->type == LAUNCH_DATA_DICTIONARY))
+ return false;
+
+ thekey = launch_data_new_string(key);
for (i = 0; i < dict->_array_cnt; i += 2) {
if (!strcasecmp(key, dict->_array[i]->string)) {
+ dict->type = LAUNCH_DATA_ARRAY;
launch_data_array_set_index(dict, thekey, i);
launch_data_array_set_index(dict, what, i + 1);
+ dict->type = LAUNCH_DATA_DICTIONARY;
return true;
}
}
+ dict->type = LAUNCH_DATA_ARRAY;
launch_data_array_set_index(dict, thekey, i);
launch_data_array_set_index(dict, what, i + 1);
+ dict->type = LAUNCH_DATA_DICTIONARY;
return true;
}
{
size_t i;
- if (LAUNCH_DATA_DICTIONARY != dict->type)
+ if (!assumes(dict->type == LAUNCH_DATA_DICTIONARY))
return NULL;
for (i = 0; i < dict->_array_cnt; i += 2) {
{
size_t i;
+ if (!assumes(dict->type == LAUNCH_DATA_DICTIONARY))
+ return false;
+
for (i = 0; i < dict->_array_cnt; i += 2) {
if (!strcasecmp(key, dict->_array[i]->string))
break;
{
size_t i;
- if (LAUNCH_DATA_DICTIONARY != dict->type)
+ if (!assumes(dict->type == LAUNCH_DATA_DICTIONARY))
return;
for (i = 0; i < dict->_array_cnt; i += 2)
bool launch_data_array_set_index(launch_data_t where, launch_data_t what, size_t ind)
{
+ if (!assumes(where->type == LAUNCH_DATA_ARRAY))
+ return false;
+
if ((ind + 1) >= where->_array_cnt) {
where->_array = realloc(where->_array, (ind + 1) * sizeof(launch_data_t));
memset(where->_array + where->_array_cnt, 0, (ind + 1 - where->_array_cnt) * sizeof(launch_data_t));
launch_data_t launch_data_array_get_index(launch_data_t where, size_t ind)
{
- if (LAUNCH_DATA_ARRAY != where->type)
+ if (!assumes(where->type == LAUNCH_DATA_ARRAY))
return NULL;
+
if (ind < where->_array_cnt)
return where->_array[ind];
return NULL;
launch_data_t launch_data_array_pop_first(launch_data_t where)
{
launch_data_t r = NULL;
+
+ if (!assumes(where->type == LAUNCH_DATA_ARRAY))
+ return NULL;
if (where->_array_cnt > 0) {
r = where->_array[0];
size_t launch_data_array_get_count(launch_data_t where)
{
- if (LAUNCH_DATA_ARRAY != where->type)
+ if (!assumes(where->type == LAUNCH_DATA_ARRAY))
return 0;
return where->_array_cnt;
}
bool launch_data_set_errno(launch_data_t d, int e)
{
+ if (!assumes(d->type == LAUNCH_DATA_ERRNO))
+ return false;
d->err = e;
return true;
}
bool launch_data_set_fd(launch_data_t d, int fd)
{
+ if (!assumes(d->type == LAUNCH_DATA_FD))
+ return false;
d->fd = fd;
return true;
}
bool launch_data_set_integer(launch_data_t d, long long n)
{
+ if (!assumes(d->type == LAUNCH_DATA_INTEGER))
+ return false;
d->number = n;
return true;
}
bool launch_data_set_bool(launch_data_t d, bool b)
{
+ if (!assumes(d->type == LAUNCH_DATA_BOOL))
+ return false;
d->boolean = b;
return true;
}
bool launch_data_set_real(launch_data_t d, double n)
{
+ if (!assumes(d->type == LAUNCH_DATA_REAL))
+ return false;
d->float_num = n;
return true;
}
bool launch_data_set_string(launch_data_t d, const char *s)
{
+ if (!assumes(d->type == LAUNCH_DATA_STRING))
+ return false;
if (d->string)
free(d->string);
d->string = strdup(s);
bool launch_data_set_opaque(launch_data_t d, const void *o, size_t os)
{
+ if (!assumes(d->type == LAUNCH_DATA_OPAQUE))
+ return false;
d->opaque_size = os;
if (d->opaque)
free(d->opaque);
int launch_data_get_errno(launch_data_t d)
{
+ if (!assumes(d->type == LAUNCH_DATA_ERRNO))
+ return 0;
return d->err;
}
int launch_data_get_fd(launch_data_t d)
{
+ if (!assumes(d->type == LAUNCH_DATA_FD))
+ return -1;
return d->fd;
}
long long launch_data_get_integer(launch_data_t d)
{
+ if (!assumes(d->type == LAUNCH_DATA_INTEGER))
+ return 0;
return d->number;
}
bool launch_data_get_bool(launch_data_t d)
{
+ if (!assumes(d->type == LAUNCH_DATA_BOOL))
+ return false;
return d->boolean;
}
double launch_data_get_real(launch_data_t d)
{
+ if (!assumes(d->type == LAUNCH_DATA_REAL))
+ return NAN;
return d->float_num;
}
const char *launch_data_get_string(launch_data_t d)
{
- if (LAUNCH_DATA_STRING != d->type)
+ if (!assumes(d->type == LAUNCH_DATA_STRING))
return NULL;
return d->string;
}
void *launch_data_get_opaque(launch_data_t d)
{
- if (LAUNCH_DATA_OPAQUE != d->type)
+ if (!assumes(d->type == LAUNCH_DATA_OPAQUE))
return NULL;
return d->opaque;
}
size_t launch_data_get_opaque_size(launch_data_t d)
{
+ if (!assumes(d->type == LAUNCH_DATA_OPAQUE))
+ return 0;
return d->opaque_size;
}
c->fd = fd;
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ assumes(fcntl(fd, F_SETFL, O_NONBLOCK) != -1);
if ((c->sendbuf = malloc(0)) == NULL)
goto out_bad;
free(lh->recvbuf);
if (lh->recvfds)
free(lh->recvfds);
- close(lh->fd);
+ assumes(close(lh->fd) != -1);
free(lh);
}
msglen = (lh->sendlen - msglen) + sizeof(struct launch_msg_header);
lmh.len = host2big(msglen);
+ lmh.fdcnt = 0;
lmh.magic = host2big(LAUNCH_MSG_HEADER_MAGIC);
iov[0].iov_base = &lmh;
if (lh->sendfdcnt > 0) {
+ lmh.fdcnt = host2big((uint64_t)lh->sendfdcnt);
sentctrllen = mh.msg_controllen = CMSG_SPACE(lh->sendfdcnt * sizeof(int));
cm = alloca(mh.msg_controllen);
mh.msg_control = cm;
cm->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cm), lh->sendfds, lh->sendfdcnt * sizeof(int));
+
}
- if ((r = sendmsg(lh->fd, &mh, 0)) == -1) {
+ if (!assumes((r = sendmsg(lh->fd, &mh, 0)) != -1)) {
return -1;
} else if (r == 0) {
errno = ECONNRESET;
if (d && launchd_msg_send(_lc->l, d) == -1) {
do {
- if (errno != EAGAIN)
+ if (!assumes(errno == EAGAIN))
goto out;
} while (launchd_msg_send(_lc->l, NULL) == -1);
}
goto out;
}
if (launchd_msg_recv(_lc->l, launch_msg_getmsgs, &resp) == -1) {
- if (errno != EAGAIN) {
+ if (!assumes(errno == EAGAIN)) {
goto out;
} else if (d == NULL) {
errno = 0;
FD_ZERO(&rfds);
FD_SET(_lc->l->fd, &rfds);
- select(_lc->l->fd + 1, &rfds, NULL, NULL, NULL);
+ assumes(select(_lc->l->fd + 1, &rfds, NULL, NULL, NULL) == 1);
}
}
}
mh.msg_control = cm;
mh.msg_controllen = 4096;
- if ((r = recvmsg(lh->fd, &mh, 0)) == -1)
+ if (!assumes((r = recvmsg(lh->fd, &mh, 0)) != -1))
return -1;
if (r == 0) {
errno = ECONNRESET;
return -1;
}
- if (mh.msg_flags & MSG_CTRUNC) {
+ if (!assumes(!(mh.msg_flags & MSG_CTRUNC))) {
errno = ECONNABORTED;
return -1;
}
lh->recvlen += r;
if (mh.msg_controllen > 0) {
+ if (!assumes(cm->cmsg_len == mh.msg_controllen)) {
+ errno = ESPIPE;
+ return -1;
+ }
lh->recvfds = realloc(lh->recvfds, lh->recvfdcnt * sizeof(int) + mh.msg_controllen - sizeof(struct cmsghdr));
memcpy(lh->recvfds + lh->recvfdcnt, CMSG_DATA(cm), mh.msg_controllen - sizeof(struct cmsghdr));
lh->recvfdcnt += (mh.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
tmplen = big2host(lmhp->len);
- if (big2host(lmhp->magic) != LAUNCH_MSG_HEADER_MAGIC || tmplen <= sizeof(struct launch_msg_header)) {
+ if (!assumes(big2host(lmhp->magic) == LAUNCH_MSG_HEADER_MAGIC) ||
+ !assumes(tmplen > sizeof(struct launch_msg_header))) {
errno = EBADRPC;
goto out_bad;
}
+ if (!assumes(big2host(lmhp->fdcnt) == lh->recvfdcnt)) {
+ errno = ERANGE;
+ return -1;
+ }
+
if (lh->recvlen < tmplen) {
goto need_more_data;
}
free(lh->recvfds);
lh->recvfds = malloc(0);
}
+
+ if (lh->recvlen == 0)
+ assumes(lh->recvfdcnt == 0);
}
return r;
static int _fd(int fd)
{
if (fd >= 0)
- fcntl(fd, F_SETFD, 1);
+ assumes(fcntl(fd, F_SETFD, 1) != -1);
return fd;
}