Always return NULL terminated strings.
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
return 0;
}
-size_t ctdb_string_len(const char *str)
+size_t ctdb_string_len(const char **in)
{
- if (str == NULL) {
+ if (*in == NULL) {
return 0;
}
- return strlen(str) + 1;
+
+ return strlen(*in) + 1;
}
-void ctdb_string_push(const char *str, uint8_t *buf)
+void ctdb_string_push(const char **in, uint8_t *buf, size_t *npush)
{
- if (str == NULL) {
- return;
+ size_t len;
+
+ len = ctdb_string_len(in);
+ if (len > 0) {
+ memcpy(buf, *in, len);
}
- memcpy(buf, str, strlen(str)+1);
+
+ *npush = len;
}
int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
- const char **out)
+ const char **out, size_t *npull)
{
- char *str;
+ const char *str;
+
+ if (buflen > UINT32_MAX) {
+ return EMSGSIZE;
+ }
if (buflen == 0) {
*out = NULL;
+ *npull = 0;
return 0;
}
}
*out = str;
+ *npull = ctdb_string_len(&str);
return 0;
}
size_t ctdb_stringn_len(const char *str)
{
- return sizeof(uint32_t) + ctdb_string_len(str);
+ return sizeof(uint32_t) + ctdb_string_len(&str);
}
void ctdb_stringn_push(const char *str, uint8_t *buf)
{
struct stringn_wire *wire = (struct stringn_wire *)buf;
+ size_t np;
- wire->length = ctdb_string_len(str);
- ctdb_string_push(str, wire->str);
+ wire->length = ctdb_string_len(&str);
+ ctdb_string_push(&str, wire->str, &np);
}
int ctdb_stringn_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
break;
case CTDB_CONTROL_DB_ATTACH:
- len = ctdb_string_len(cd->data.db_name);
+ len = ctdb_string_len(&cd->data.db_name);
break;
case CTDB_CONTROL_SET_CALL:
break;
case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
- len = ctdb_string_len(cd->data.db_name);
+ len = ctdb_string_len(&cd->data.db_name);
break;
case CTDB_CONTROL_UPDATE_RECORD:
break;
case CTDB_CONTROL_DB_ATTACH_REPLICATED:
- len = ctdb_string_len(cd->data.db_name);
+ len = ctdb_string_len(&cd->data.db_name);
break;
}
break;
case CTDB_CONTROL_DB_ATTACH:
- ctdb_string_push(cd->data.db_name, buf);
+ ctdb_string_push(&cd->data.db_name, buf, &np);
break;
case CTDB_CONTROL_SET_CALL:
break;
case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
- ctdb_string_push(cd->data.db_name, buf);
+ ctdb_string_push(&cd->data.db_name, buf, &np);
break;
case CTDB_CONTROL_UPDATE_RECORD:
break;
case CTDB_CONTROL_DB_ATTACH_REPLICATED:
- ctdb_string_push(cd->data.db_name, buf);
+ ctdb_string_push(&cd->data.db_name, buf, &np);
break;
}
}
case CTDB_CONTROL_DB_ATTACH:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.db_name);
+ &cd->data.db_name, &np);
break;
case CTDB_CONTROL_SET_CALL:
case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.db_name);
+ &cd->data.db_name, &np);
break;
case CTDB_CONTROL_UPDATE_RECORD:
case CTDB_CONTROL_DB_ATTACH_REPLICATED:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.db_name);
+ &cd->data.db_name, &np);
break;
}
break;
case CTDB_CONTROL_GETDBPATH:
- len = ctdb_string_len(cd->data.db_path);
+ len = ctdb_string_len(&cd->data.db_path);
break;
case CTDB_CONTROL_GETVNNMAP:
break;
case CTDB_CONTROL_GET_DBNAME:
- len = ctdb_string_len(cd->data.db_name);
+ len = ctdb_string_len(&cd->data.db_name);
break;
case CTDB_CONTROL_ENABLE_SEQNUM:
break;
case CTDB_CONTROL_DUMP_MEMORY:
- len = ctdb_string_len(cd->data.mem_str);
+ len = ctdb_string_len(&cd->data.mem_str);
break;
case CTDB_CONTROL_GET_PID:
break;
case CTDB_CONTROL_GET_RECLOCK_FILE:
- len = ctdb_string_len(cd->data.reclock_file);
+ len = ctdb_string_len(&cd->data.reclock_file);
break;
case CTDB_CONTROL_STOP_NODE:
break;
case CTDB_CONTROL_DB_GET_HEALTH:
- len = ctdb_string_len(cd->data.reason);
+ len = ctdb_string_len(&cd->data.reason);
break;
case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
break;
case CTDB_CONTROL_GETDBPATH:
- ctdb_string_push(cd->data.db_path, buf);
+ ctdb_string_push(&cd->data.db_path, buf, &np);
break;
case CTDB_CONTROL_GETVNNMAP:
break;
case CTDB_CONTROL_GET_DBNAME:
- ctdb_string_push(cd->data.db_name, buf);
+ ctdb_string_push(&cd->data.db_name, buf, &np);
break;
case CTDB_CONTROL_DUMP_MEMORY:
- ctdb_string_push(cd->data.mem_str, buf);
+ ctdb_string_push(&cd->data.mem_str, buf, &np);
break;
case CTDB_CONTROL_GET_PID:
break;
case CTDB_CONTROL_GET_RECLOCK_FILE:
- ctdb_string_push(cd->data.reclock_file, buf);
+ ctdb_string_push(&cd->data.reclock_file, buf, &np);
break;
case CTDB_CONTROL_GET_BAN_STATE:
break;
case CTDB_CONTROL_DB_GET_HEALTH:
- ctdb_string_push(cd->data.reason, buf);
+ ctdb_string_push(&cd->data.reason, buf, &np);
break;
case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
case CTDB_CONTROL_GETDBPATH:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.db_path);
+ &cd->data.db_path, &np);
break;
case CTDB_CONTROL_GETVNNMAP:
case CTDB_CONTROL_GET_DBNAME:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.db_name);
+ &cd->data.db_name, &np);
break;
case CTDB_CONTROL_DUMP_MEMORY:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.mem_str);
+ &cd->data.mem_str, &np);
break;
case CTDB_CONTROL_GET_PID:
case CTDB_CONTROL_GET_RECLOCK_FILE:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.reclock_file);
+ &cd->data.reclock_file, &np);
break;
case CTDB_CONTROL_GET_BAN_STATE:
case CTDB_CONTROL_DB_GET_HEALTH:
ret = ctdb_string_pull(buf, buflen, mem_ctx,
- &cd->data.reason);
+ &cd->data.reason, &np);
break;
case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
return offsetof(struct ctdb_reply_control_wire, data) +
(c->status == 0 ?
ctdb_reply_control_data_len(&c->rdata) :
- ctdb_string_len(c->errmsg));
+ ctdb_string_len(&c->errmsg));
}
int ctdb_reply_control_push(struct ctdb_req_header *h,
{
struct ctdb_reply_control_wire *wire =
(struct ctdb_reply_control_wire *)buf;
- size_t length;
+ size_t length, np;
length = ctdb_reply_control_len(h, reply);
if (*buflen < length) {
ctdb_reply_control_data_push(&reply->rdata, wire->data);
} else {
wire->datalen = 0;
- wire->errorlen = ctdb_string_len(reply->errmsg);
- ctdb_string_push(reply->errmsg, wire->data + wire->datalen);
+ wire->errorlen = ctdb_string_len(&reply->errmsg);
+ ctdb_string_push(&reply->errmsg, wire->data + wire->datalen,
+ &np);
}
return 0;
{
struct ctdb_reply_control_wire *wire =
(struct ctdb_reply_control_wire *)buf;
- size_t length;
+ size_t length, np;
int ret;
length = offsetof(struct ctdb_reply_control_wire, data);
}
ret = ctdb_string_pull(wire->data + wire->datalen, wire->errorlen,
- mem_ctx, &c->errmsg);
+ mem_ctx, &c->errmsg, &np);
if (ret != 0) {
return ret;
}
break;
case CTDB_SRVID_RELEASE_IP:
- len = ctdb_string_len(mdata->ipaddr);
+ len = ctdb_string_len(&mdata->ipaddr);
break;
case CTDB_SRVID_TAKE_IP:
- len = ctdb_string_len(mdata->ipaddr);
+ len = ctdb_string_len(&mdata->ipaddr);
break;
case CTDB_SRVID_SET_NODE_FLAGS:
break;
case CTDB_SRVID_RELEASE_IP:
- ctdb_string_push(mdata->ipaddr, buf);
+ ctdb_string_push(&mdata->ipaddr, buf, &np);
break;
case CTDB_SRVID_TAKE_IP:
- ctdb_string_push(mdata->ipaddr, buf);
+ ctdb_string_push(&mdata->ipaddr, buf, &np);
break;
case CTDB_SRVID_SET_NODE_FLAGS:
break;
case CTDB_SRVID_RELEASE_IP:
- ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr);
+ ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr,
+ &np);
break;
case CTDB_SRVID_TAKE_IP:
- ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr);
+ ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr,
+ &np);
break;
case CTDB_SRVID_SET_NODE_FLAGS:
int ctdb_chararray_pull(uint8_t *buf, size_t buflen, char *out, size_t len,
size_t *npull);
-size_t ctdb_string_len(const char *str);
-void ctdb_string_push(const char *str, uint8_t *buf);
+size_t ctdb_string_len(const char **in);
+void ctdb_string_push(const char **in, uint8_t *buf, size_t *npush);
int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
- const char **out);
+ const char **out, size_t *npull);
size_t ctdb_stringn_len(const char *str);
void ctdb_stringn_push(const char *str, uint8_t *buf);
assert(strncmp(p1, p2, len) == 0);
}
-static void test_ctdb_string(void)
-{
- TALLOC_CTX *mem_ctx = talloc_new(NULL);
- const char *p1, *p2;
- size_t buflen;
- int ret;
-
- fill_ctdb_string(mem_ctx, &p1);
- buflen = ctdb_string_len(p1);
- ctdb_string_push(p1, BUFFER);
- ret = ctdb_string_pull(BUFFER, buflen, mem_ctx, &p2);
- assert(ret == 0);
- verify_ctdb_string(p1, p2);
- talloc_free(mem_ctx);
-}
+PROTOCOL_TYPE2_TEST(const char *, ctdb_string);
static void test_ctdb_stringn(void)
{
ctdb_stringn_push(p1, BUFFER);
ret = ctdb_stringn_pull(BUFFER, buflen, mem_ctx, &p2);
assert(ret == 0);
- verify_ctdb_string(p1, p2);
+ verify_ctdb_string(&p1, &p2);
talloc_free(mem_ctx);
}
test_ctdb_chararray();
- test_ctdb_string();
+ TEST_FUNC(ctdb_string)();
test_ctdb_stringn();
test_ctdb_pid();
}
}
+static void fill_string(char *p, size_t len)
+{
+ int i;
+
+ for (i=0; i<len-1; i++) {
+ p[i] = 'A' + rand_int(26);
+ }
+ p[len-1] = '\0';
+}
+
+static void verify_string(const char *p1, const char *p2)
+{
+ assert(strlen(p1) == strlen(p2));
+ assert(strcmp(p1, p2) == 0);
+}
+
void fill_ctdb_uint8(uint8_t *p)
{
*p = rand8();
assert(*p1 == *p2);
}
-void fill_ctdb_string(TALLOC_CTX *mem_ctx, const char **out)
+void fill_ctdb_string(TALLOC_CTX *mem_ctx, const char **p)
{
- char *p;
- int len, i;
+ char *str;
+ int len;
- len = rand_int(1024) + 1;
- p = talloc_size(mem_ctx, len+1);
- assert(p != NULL);
+ len = rand_int(1024) + 2;
+ str = talloc_size(mem_ctx, len+1);
+ assert(str != NULL);
- for (i=0; i<len; i++) {
- p[i] = 'A' + rand_int(26);
- }
- p[len] = '\0';
- *out = p;
+ fill_string(str, len);
+ *p = str;
}
-void verify_ctdb_string(const char *p1, const char *p2)
+void verify_ctdb_string(const char **p1, const char **p2)
{
- if (p1 == NULL || p2 == NULL) {
- assert(p1 == p2);
+ if (*p1 == NULL || *p2 == NULL) {
+ assert(*p1 == *p2);
} else {
- assert(strlen(p1) == strlen(p2));
- assert(strcmp(p1, p2) == 0);
+ verify_string(*p1, *p2);
}
}
void fill_ctdb_tunable(TALLOC_CTX *mem_ctx, struct ctdb_tunable *p)
{
- fill_ctdb_string(mem_ctx, discard_const(&p->name));
+ fill_ctdb_string(mem_ctx, &p->name);
p->value = rand32();
}
void verify_ctdb_tunable(struct ctdb_tunable *p1, struct ctdb_tunable *p2)
{
- verify_ctdb_string(discard_const(p1->name), discard_const(p2->name));
+ verify_ctdb_string(&p1->name, &p2->name);
assert(p1->value == p2->value);
}
p->count = rand_int(100) + 1;
p->var = talloc_array(mem_ctx, const char *, p->count);
for (i=0; i<p->count; i++) {
- fill_ctdb_string(p->var, discard_const(&p->var[i]));
+ fill_ctdb_string(p->var, &p->var[i]);
}
}
assert(p1->count == p2->count);
for (i=0; i<p1->count; i++) {
- verify_ctdb_string(discard_const(p1->var[i]),
- discard_const(p2->var[i]));
+ verify_ctdb_string(&p1->var[i], &p2->var[i]);
}
}
{
verify_ctdb_sock_addr(&p1->addr, &p2->addr);
assert(p1->mask == p2->mask);
- verify_ctdb_string(p1->iface, p2->iface);
+ verify_ctdb_string(&p1->iface, &p2->iface);
}
void fill_ctdb_transdb(TALLOC_CTX *mem_ctx, struct ctdb_transdb *p)
void fill_ctdb_bool(bool *p);
void verify_ctdb_bool(bool *p1, bool *p2);
-void fill_ctdb_string(TALLOC_CTX *mem_ctx, const char **out);
-void verify_ctdb_string(const char *p1, const char *p2);
+void fill_ctdb_string(TALLOC_CTX *mem_ctx, const char **p);
+void verify_ctdb_string(const char **p1, const char **p2);
void fill_tdb_data_nonnull(TALLOC_CTX *mem_ctx, TDB_DATA *p);
void fill_tdb_data(TALLOC_CTX *mem_ctx, TDB_DATA *p);
break;
case CTDB_CONTROL_DB_ATTACH:
- verify_ctdb_string(cd->data.db_name, cd2->data.db_name);
+ verify_ctdb_string(&cd->data.db_name, &cd2->data.db_name);
break;
case CTDB_CONTROL_SET_CALL:
break;
case CTDB_CONTROL_GET_TUNABLE:
- verify_ctdb_string(cd->data.tun_var, cd2->data.tun_var);
+ verify_ctdb_string(&cd->data.tun_var, &cd2->data.tun_var);
break;
case CTDB_CONTROL_LIST_TUNABLES:
break;
case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
- verify_ctdb_string(cd->data.db_name, cd2->data.db_name);
+ verify_ctdb_string(&cd->data.db_name, &cd2->data.db_name);
break;
case CTDB_CONTROL_UPDATE_RECORD:
break;
case CTDB_CONTROL_DB_ATTACH_REPLICATED:
- verify_ctdb_string(cd->data.db_name, cd2->data.db_name);
+ verify_ctdb_string(&cd->data.db_name, &cd2->data.db_name);
break;
}
break;
case CTDB_CONTROL_GETDBPATH:
- verify_ctdb_string(cd->data.db_path, cd2->data.db_path);
+ verify_ctdb_string(&cd->data.db_path, &cd2->data.db_path);
break;
case CTDB_CONTROL_GETVNNMAP:
break;
case CTDB_CONTROL_GET_DBNAME:
- verify_ctdb_string(cd->data.db_name, cd2->data.db_name);
+ verify_ctdb_string(&cd->data.db_name, &cd2->data.db_name);
break;
case CTDB_CONTROL_ENABLE_SEQNUM:
break;
case CTDB_CONTROL_DUMP_MEMORY:
- verify_ctdb_string(cd->data.mem_str, cd2->data.mem_str);
+ verify_ctdb_string(&cd->data.mem_str, &cd2->data.mem_str);
break;
case CTDB_CONTROL_GET_PID:
break;
case CTDB_CONTROL_GET_RECLOCK_FILE:
- verify_ctdb_string(cd->data.reclock_file,
- cd2->data.reclock_file);
+ verify_ctdb_string(&cd->data.reclock_file,
+ &cd2->data.reclock_file);
break;
case CTDB_CONTROL_STOP_NODE:
break;
case CTDB_CONTROL_DB_GET_HEALTH:
- verify_ctdb_string(cd->data.reason, cd2->data.reason);
+ verify_ctdb_string(&cd->data.reason, &cd2->data.reason);
break;
case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
struct ctdb_reply_control *c2)
{
assert(c->status == c2->status);
- verify_ctdb_string(c->errmsg, c2->errmsg);
+ verify_ctdb_string(&c->errmsg, &c2->errmsg);
if (c->status == 0) {
verify_ctdb_reply_control_data(&c->rdata, &c2->rdata);
}
{
assert(p1->event == p2->event);
assert(p1->timeout == p2->timeout);
- verify_ctdb_string(p1->arg_str, p2->arg_str);
+ verify_ctdb_string(&p1->arg_str, &p2->arg_str);
}
void fill_ctdb_event_request_status(TALLOC_CTX *mem_ctx,
struct ctdb_event_request_script_enable *p1,
struct ctdb_event_request_script_enable *p2)
{
- verify_ctdb_string(p1->script_name, p2->script_name);
+ verify_ctdb_string(&p1->script_name, &p2->script_name);
}
void fill_ctdb_event_request_script_disable(TALLOC_CTX *mem_ctx,
struct ctdb_event_request_script_disable *p1,
struct ctdb_event_request_script_disable *p2)
{
- verify_ctdb_string(p1->script_name, p2->script_name);
+ verify_ctdb_string(&p1->script_name, &p2->script_name);
}
void fill_ctdb_event_reply_status(TALLOC_CTX *mem_ctx,