summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2023-03-13 17:42:50 -0400
committerGreg Hudson <ghudson@mit.edu>2023-03-24 14:45:58 -0400
commitfc1ad91f68a06dfc9b082897120985d45438fa9f (patch)
tree21762c8bdeef858858cbf43946e5ae4c78810c54
parentceb0d82f0a9f69615ca4f5ff3bbf92af17f610ac (diff)
downloadkrb5-fc1ad91f68a06dfc9b082897120985d45438fa9f.tar.gz
Make k5buf more flexible for binary data
Remove the invariant that buf.data is always zero-terminated, to allow marshalling of binary data into precisely allocated fixed regions. Add k5_buf_cstring() to zero-terminate the buffer and retrieve the data pointer. Adjust all callers that build C strings appropriately. Add a k5_buf_add_byte() convenience wrapper alongside the integer marshalling wrappers. Change k5_buf_init_fixed() to accept a void pointer so it can more conveniently be used with uint8_t arrays.
-rw-r--r--src/clients/ksu/authorization.c4
-rw-r--r--src/clients/kvno/kvno.c9
-rw-r--r--src/include/k5-buf.h20
-rw-r--r--src/kadmin/dbutil/tdumputil.c2
-rw-r--r--src/kadmin/server/auth_acl.c2
-rw-r--r--src/kdc/kdc_util.c4
-rw-r--r--src/lib/gssapi/spnego/negoex_util.c7
-rw-r--r--src/lib/kadm5/logger.c7
-rw-r--r--src/lib/krb5/krb/chpw.c11
-rw-r--r--src/lib/krb5/krb/kerrs.c2
-rw-r--r--src/lib/krb5/krb/preauth_otp.c7
-rw-r--r--src/lib/krb5/os/dnsglue.c2
-rw-r--r--src/lib/krb5/os/dnssrv.c2
-rw-r--r--src/lib/krb5/os/expand_path.c13
-rw-r--r--src/lib/krb5/os/localauth_rule.c11
-rw-r--r--src/lib/krb5/os/trace.c2
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c10
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c8
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c2
-rw-r--r--src/plugins/preauth/pkinit/pkinit_crypto_openssl.c8
-rw-r--r--src/util/support/json.c6
-rw-r--r--src/util/support/k5buf.c27
-rw-r--r--src/util/support/libkrb5support-fixed.exports1
-rw-r--r--src/util/support/t_k5buf.c17
-rw-r--r--src/util/support/utf8_conv.c4
25 files changed, 101 insertions, 87 deletions
diff --git a/src/clients/ksu/authorization.c b/src/clients/ksu/authorization.c
index 6ea10844f..fb9d5d094 100644
--- a/src/clients/ksu/authorization.c
+++ b/src/clients/ksu/authorization.c
@@ -501,11 +501,11 @@ krb5_boolean find_first_cmd_that_exists(fcmd_arr, cmd_out, err_out)
for(j= 0; j < i; j ++)
k5_buf_add_fmt(&buf, " %s ", fcmd_arr[j]);
k5_buf_add(&buf, "\n");
- if (k5_buf_status(&buf) != 0) {
+ *err_out = k5_buf_cstring(&buf);
+ if (*err_out == NULL) {
perror(prog_name);
exit(1);
}
- *err_out = buf.data;
}
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
index 7f8667ce4..03f72f596 100644
--- a/src/clients/kvno/kvno.c
+++ b/src/clients/kvno/kvno.c
@@ -222,7 +222,7 @@ read_pem_file(char *file_name, krb5_data *der_out)
FILE *fp = NULL;
const char *begin_line = "-----BEGIN CERTIFICATE-----";
const char *end_line = "-----END ", *line;
- char linebuf[256];
+ char linebuf[256], *b64;
struct k5buf buf = EMPTY_K5BUF;
uint8_t *der_cert;
size_t dlen;
@@ -267,7 +267,12 @@ read_pem_file(char *file_name, krb5_data *der_out)
k5_buf_add(&buf, line);
}
- der_cert = k5_base64_decode(buf.data, &dlen);
+ b64 = k5_buf_cstring(&buf);
+ if (b64 == NULL) {
+ ret = ENOMEM;
+ goto cleanup;
+ }
+ der_cert = k5_base64_decode(b64, &dlen);
if (der_cert == NULL) {
ret = EINVAL;
k5_setmsg(context, ret, _("Invalid base64"));
diff --git a/src/include/k5-buf.h b/src/include/k5-buf.h
index f2cdb0cbe..0db90ccff 100644
--- a/src/include/k5-buf.h
+++ b/src/include/k5-buf.h
@@ -35,8 +35,9 @@
* fixed or dynamic buffer without the need to check for a failure at each step
* (and without aborting on malloc failure). If an allocation failure occurs
* or the fixed buffer runs out of room, the buffer will be set to an error
- * state which can be detected with k5_buf_status. Data in a buffer is
- * terminated with a zero byte so that it can be used as a C string.
+ * state which can be detected with k5_buf_status. Data in a buffer is not
+ * automatically terminated with a zero byte; call k5_buf_cstring() to use the
+ * contents as a C string.
*
* k5buf structures are usually stack-allocated. Do not put k5buf structure
* pointers into public APIs. It is okay to reference the data and len fields
@@ -58,7 +59,7 @@ struct k5buf {
/* Initialize a k5buf using a fixed-sized, existing buffer. SPACE must be
* more than zero, or an assertion failure will result. */
-void k5_buf_init_fixed(struct k5buf *buf, char *data, size_t space);
+void k5_buf_init_fixed(struct k5buf *buf, void *data, size_t space);
/* Initialize a k5buf using an internally allocated dynamic buffer. */
void k5_buf_init_dynamic(struct k5buf *buf);
@@ -73,7 +74,8 @@ void k5_buf_add(struct k5buf *buf, const char *data);
/* Add a counted series of bytes to BUF. */
void k5_buf_add_len(struct k5buf *buf, const void *data, size_t len);
-/* Add sprintf-style formatted data to BUF. */
+/* Add sprintf-style formatted data to BUF. For a fixed-length buffer this
+ * operation will fail if there isn't room for a zero terminator. */
void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
#if !defined(__cplusplus) && (__GNUC__ > 2)
__attribute__((__format__(__printf__, 2, 3)))
@@ -88,6 +90,10 @@ void k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
#endif
;
+/* Without changing the length of buf, ensure that there is a zero byte after
+ * buf.data and return it. Return NULL on error. */
+char *k5_buf_cstring(struct k5buf *buf);
+
/* Extend the length of buf by len and return a pointer to the reserved space,
* to be filled in by the caller. Return NULL on error. */
void *k5_buf_get_space(struct k5buf *buf, size_t len);
@@ -109,6 +115,12 @@ int k5_buf_status(struct k5buf *buf);
void k5_buf_free(struct k5buf *buf);
static inline void
+k5_buf_add_byte(struct k5buf *buf, uint8_t val)
+{
+ k5_buf_add_len(buf, &val, 1);
+}
+
+static inline void
k5_buf_add_uint16_be(struct k5buf *buf, uint16_t val)
{
void *p = k5_buf_get_space(buf, 2);
diff --git a/src/kadmin/dbutil/tdumputil.c b/src/kadmin/dbutil/tdumputil.c
index 2c14d5670..076cfa971 100644
--- a/src/kadmin/dbutil/tdumputil.c
+++ b/src/kadmin/dbutil/tdumputil.c
@@ -92,7 +92,7 @@ qquote(struct flavor *fl, const char *s)
if (*sp == fl->quotechar)
k5_buf_add_len(&buf, sp, 1);
}
- return buf.data;
+ return k5_buf_cstring(&buf);
}
/*
diff --git a/src/kadmin/server/auth_acl.c b/src/kadmin/server/auth_acl.c
index efe9c6961..ce9ace36a 100644
--- a/src/kadmin/server/auth_acl.c
+++ b/src/kadmin/server/auth_acl.c
@@ -146,7 +146,7 @@ get_line(FILE *fp, const char *fname, int *lineno, int *incr)
*incr = 0;
k5_buf_truncate(&buf, 0);
} else {
- return buf.data;
+ return k5_buf_cstring(&buf);
}
}
}
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 932eeb880..df0d35f60 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1135,7 +1135,7 @@ ktypes2str(krb5_enctype *ktype, int nktypes)
k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]);
}
k5_buf_add(&buf, "}");
- return buf.data;
+ return k5_buf_cstring(&buf);
}
char *
@@ -1164,7 +1164,7 @@ rep_etypes2str(krb5_kdc_rep *rep)
}
k5_buf_add(&buf, "}");
- return buf.data;
+ return k5_buf_cstring(&buf);
}
static krb5_error_code
diff --git a/src/lib/gssapi/spnego/negoex_util.c b/src/lib/gssapi/spnego/negoex_util.c
index 99580fd79..edc5462e8 100644
--- a/src/lib/gssapi/spnego/negoex_util.c
+++ b/src/lib/gssapi/spnego/negoex_util.c
@@ -157,7 +157,7 @@ guid_to_string(const uint8_t guid[GUID_LENGTH])
k5_buf_init_dynamic(&buf);
add_guid(&buf, guid);
- return buf.data;
+ return k5_buf_cstring(&buf);
}
/* Check that the described vector lies within the message, and return a
@@ -188,7 +188,7 @@ trace_received_message(spnego_gss_ctx_id_t ctx,
if (i + 1 < msg->u.n.nschemes)
k5_buf_add(&buf, " ");
}
- info = buf.data;
+ info = k5_buf_cstring(&buf);
} else if (msg->type == INITIATOR_META_DATA ||
msg->type == ACCEPTOR_META_DATA ||
msg->type == CHALLENGE || msg->type == AP_REQUEST) {
@@ -613,7 +613,8 @@ negoex_add_nego_message(spnego_gss_ctx_id_t ctx, enum message_type type,
if (buf.len > 0) {
k5_buf_truncate(&buf, buf.len - 1);
- TRACE_NEGOEX_OUTGOING(ctx->kctx, seqnum, typestr(type), buf.data);
+ TRACE_NEGOEX_OUTGOING(ctx->kctx, seqnum, typestr(type),
+ k5_buf_cstring(&buf));
k5_buf_free(&buf);
}
}
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
index c6885edf2..e14da5379 100644
--- a/src/lib/kadm5/logger.c
+++ b/src/lib/kadm5/logger.c
@@ -182,7 +182,7 @@ static void
klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
{
struct k5buf buf;
- const char *emsg;
+ const char *emsg, *msg;
if (format == NULL)
return;
@@ -200,8 +200,9 @@ klog_com_err_proc(const char *whoami, long int code, const char *format, va_list
/* Add the formatted message. */
k5_buf_add_vfmt(&buf, format, ap);
- if (k5_buf_status(&buf) == 0)
- krb5_klog_syslog(code ? LOG_ERR : LOG_INFO, "%s", (char *)buf.data);
+ msg = k5_buf_cstring(&buf);
+ if (msg != NULL)
+ krb5_klog_syslog(code ? LOG_ERR : LOG_INFO, "%s", msg);
k5_buf_free(&buf);
}
diff --git a/src/lib/krb5/krb/chpw.c b/src/lib/krb5/krb/chpw.c
index 803c80feb..aca394592 100644
--- a/src/lib/krb5/krb/chpw.c
+++ b/src/lib/krb5/krb/chpw.c
@@ -393,6 +393,7 @@ decode_ad_policy_info(const krb5_data *data, char **msg_out)
uint64_t password_days;
const char *p;
struct k5buf buf;
+ char *msg;
*msg_out = NULL;
if (data->length != AD_POLICY_INFO_LENGTH)
@@ -462,13 +463,13 @@ decode_ad_policy_info(const krb5_data *data, char **msg_out)
(int)password_days);
}
- if (k5_buf_status(&buf) != 0)
+ msg = k5_buf_cstring(&buf);
+ if (msg == NULL)
return ENOMEM;
-
- if (buf.len > 0)
- *msg_out = buf.data;
+ if (*msg != '\0')
+ *msg_out = msg;
else
- k5_buf_free(&buf);
+ free(msg);
return 0;
}
diff --git a/src/lib/krb5/krb/kerrs.c b/src/lib/krb5/krb/kerrs.c
index 0146d9a41..0e8167929 100644
--- a/src/lib/krb5/krb/kerrs.c
+++ b/src/lib/krb5/krb/kerrs.c
@@ -165,7 +165,7 @@ err_fmt_fmt(const char *err_fmt, long code, const char *msg)
s += 2;
}
k5_buf_add(&buf, s); /* Remainder after last token */
- return buf.data;
+ return k5_buf_cstring(&buf);
}
const char * KRB5_CALLCONV
diff --git a/src/lib/krb5/krb/preauth_otp.c b/src/lib/krb5/krb/preauth_otp.c
index 5305d9a29..38eaf426c 100644
--- a/src/lib/krb5/krb/preauth_otp.c
+++ b/src/lib/krb5/krb/preauth_otp.c
@@ -504,7 +504,7 @@ prompt_for_tokeninfo(krb5_context context, krb5_prompter_fct prompter,
void *prompter_data, krb5_otp_tokeninfo **tis,
krb5_otp_tokeninfo **out_ti)
{
- char response[1024];
+ char response[1024], *prompt;
krb5_otp_tokeninfo *ti = NULL;
krb5_error_code retval = 0;
struct k5buf buf;
@@ -517,11 +517,12 @@ prompt_for_tokeninfo(krb5_context context, krb5_prompter_fct prompter,
k5_buf_add_len(&buf, tis[i]->vendor.data, tis[i]->vendor.length);
k5_buf_add(&buf, "\n");
}
- if (k5_buf_status(&buf) != 0)
+ prompt = k5_buf_cstring(&buf);
+ if (prompt == NULL)
return ENOMEM;
do {
- retval = doprompt(context, prompter, prompter_data, buf.data,
+ retval = doprompt(context, prompter, prompter_data, prompt,
_("Enter #"), response, sizeof(response));
if (retval != 0)
goto cleanup;
diff --git a/src/lib/krb5/os/dnsglue.c b/src/lib/krb5/os/dnsglue.c
index 0cd213fdd..668a7a69a 100644
--- a/src/lib/krb5/os/dnsglue.c
+++ b/src/lib/krb5/os/dnsglue.c
@@ -392,7 +392,7 @@ txt_lookup_name(const char *prefix, const char *name)
k5_buf_add(&buf, ".");
}
- return buf.data;
+ return k5_buf_cstring(&buf);
}
/*
diff --git a/src/lib/krb5/os/dnssrv.c b/src/lib/krb5/os/dnssrv.c
index 5992a9bdf..62d6d1371 100644
--- a/src/lib/krb5/os/dnssrv.c
+++ b/src/lib/krb5/os/dnssrv.c
@@ -72,7 +72,7 @@ make_lookup_name(const krb5_data *realm, const char *service,
if (buf.len > 0 && ((char *)buf.data)[buf.len - 1] != '.')
k5_buf_add(&buf, ".");
- return buf.data;
+ return k5_buf_cstring(&buf);
}
/* Insert new into the list *head, ordering by priority. Weight is not
diff --git a/src/lib/krb5/os/expand_path.c b/src/lib/krb5/os/expand_path.c
index 4ce466c19..5cbccf08c 100644
--- a/src/lib/krb5/os/expand_path.c
+++ b/src/lib/krb5/os/expand_path.c
@@ -454,7 +454,7 @@ k5_expand_path_tokens_extra(krb5_context context, const char *path_in,
{
krb5_error_code ret;
struct k5buf buf;
- char *tok_begin, *tok_end, *tok_val, **extra_tokens = NULL;
+ char *tok_begin, *tok_end, *tok_val, **extra_tokens = NULL, *path;
const char *path_left;
size_t nargs = 0, i;
va_list ap;
@@ -517,22 +517,25 @@ k5_expand_path_tokens_extra(krb5_context context, const char *path_in,
path_left = tok_end + 1;
}
- ret = k5_buf_status(&buf);
- if (ret)
+ path = k5_buf_cstring(&buf);
+ if (path == NULL) {
+ ret = ENOMEM;
goto cleanup;
+ }
#ifdef _WIN32
/* Also deal with slashes. */
{
char *p;
- for (p = buf.data; *p != '\0'; p++) {
+ for (p = path; *p != '\0'; p++) {
if (*p == '/')
*p = '\\';
}
}
#endif
- *path_out = buf.data;
+ *path_out = path;
memset(&buf, 0, sizeof(buf));
+ ret = 0;
cleanup:
k5_buf_free(&buf);
diff --git a/src/lib/krb5/os/localauth_rule.c b/src/lib/krb5/os/localauth_rule.c
index 8be29c415..056857633 100644
--- a/src/lib/krb5/os/localauth_rule.c
+++ b/src/lib/krb5/os/localauth_rule.c
@@ -130,10 +130,8 @@ do_replacement(const char *regstr, const char *repl, krb5_boolean doall,
}
regfree(&re);
k5_buf_add(&buf, instr);
- if (k5_buf_status(&buf) != 0)
- return ENOMEM;
- *outstr = buf.data;
- return 0;
+ *outstr = k5_buf_cstring(&buf);
+ return (*outstr == NULL) ? ENOMEM : 0;
}
/*
@@ -265,11 +263,10 @@ aname_get_selstring(krb5_context context, krb5_const_principal aname,
return KRB5_CONFIG_BADFORMAT;
}
- if (k5_buf_status(&selstring) != 0)
+ *selstring_out = k5_buf_cstring(&selstring);
+ if (*selstring_out == NULL)
return ENOMEM;
-
*contextp = current + 1;
- *selstring_out = selstring.data;
return 0;
}
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index 3369fc4ba..5f64ca8d6 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -366,7 +366,7 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
creds->client, creds->server);
}
}
- return buf.data;
+ return k5_buf_cstring(&buf);
}
/* Allows trace_format formatters to be represented in terms of other
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
index 6bc20593f..b3bf1ba6d 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
@@ -1370,7 +1370,7 @@ get_ldap_auth_ind(krb5_context context, LDAP *ld, LDAPMessage *ldap_ent,
{
krb5_error_code ret;
int i;
- char **auth_inds = NULL;
+ char **auth_inds = NULL, *indstr;
struct k5buf buf = EMPTY_K5BUF;
auth_inds = ldap_get_values(ld, ldap_ent, "krbPrincipalAuthInd");
@@ -1386,12 +1386,14 @@ get_ldap_auth_ind(krb5_context context, LDAP *ld, LDAPMessage *ldap_ent,
k5_buf_add(&buf, " ");
}
- ret = k5_buf_status(&buf);
- if (ret)
+ indstr = k5_buf_cstring(&buf);
+ if (indstr == NULL) {
+ ret = ENOMEM;
goto cleanup;
+ }
ret = krb5_dbe_set_string(context, entry, KRB5_KDB_SK_REQUIRE_AUTH,
- buf.data);
+ indstr);
if (!ret)
*mask |= KDB_AUTH_IND_ATTR;
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
index b5a4e5f76..6328fbe2b 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
@@ -614,8 +614,6 @@ krb5_ldap_parse_principal_name(char *i_princ_name, char **o_princ_name)
at_rlm_name = strrchr(i_princ_name, '@');
if (!at_rlm_name) {
*o_princ_name = strdup(i_princ_name);
- if (!*o_princ_name)
- return ENOMEM;
} else {
k5_buf_init_dynamic(&buf);
for (p = i_princ_name; p < at_rlm_name; p++) {
@@ -624,9 +622,7 @@ krb5_ldap_parse_principal_name(char *i_princ_name, char **o_princ_name)
k5_buf_add_len(&buf, p, 1);
}
k5_buf_add(&buf, at_rlm_name);
- if (k5_buf_status(&buf) != 0)
- return ENOMEM;
- *o_princ_name = buf.data;
+ *o_princ_name = k5_buf_cstring(&buf);
}
- return 0;
+ return (*o_princ_name == NULL) ? ENOMEM : 0;
}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
index 3daf52493..753929b06 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
@@ -87,7 +87,7 @@ ldap_filter_correct (char *in)
break;
k5_buf_add_fmt(&buf, "\\%2x", (unsigned char)*in++);
}
- return buf.data;
+ return k5_buf_cstring(&buf);
}
static int
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 6ae6425d8..f41328763 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -4406,7 +4406,6 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts)
{
struct k5buf buf;
int n = 0;
- char *ret;
k5_buf_init_dynamic(&buf);
k5_buf_add(&buf, "PKCS11:");
@@ -4431,12 +4430,7 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts)
k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "",
(long)idopts->slotid);
}
- if (k5_buf_status(&buf) == 0)
- ret = strdup(buf.data);
- else
- ret = NULL;
- k5_buf_free(&buf);
- return ret;
+ return k5_buf_cstring(&buf);
}
static krb5_error_code
diff --git a/src/util/support/json.c b/src/util/support/json.c
index ae2feae97..ac2e5be0b 100644
--- a/src/util/support/json.c
+++ b/src/util/support/json.c
@@ -696,10 +696,8 @@ k5_json_encode(k5_json_value val, char **json_out)
k5_buf_free(&buf);
return ret;
}
- if (k5_buf_status(&buf) != 0)
- return ENOMEM;
- *json_out = buf.data;
- return 0;
+ *json_out = k5_buf_cstring(&buf);
+ return (*json_out == NULL) ? ENOMEM : 0;
}
/*** JSON decoding ***/
diff --git a/src/util/support/k5buf.c b/src/util/support/k5buf.c
index b2b5e5b67..a17d2310f 100644
--- a/src/util/support/k5buf.c
+++ b/src/util/support/k5buf.c
@@ -73,13 +73,13 @@ ensure_space(struct k5buf *buf, size_t len)
if (buf->buftype == K5BUF_ERROR)
return 0;
- if (buf->space - 1 - buf->len >= len) /* Enough room already. */
+ if (buf->space - buf->len >= len) /* Enough room already. */
return 1;
if (buf->buftype == K5BUF_FIXED) /* Can't resize a fixed buffer. */
goto error_exit;
assert(buf->buftype == K5BUF_DYNAMIC || buf->buftype == K5BUF_DYNAMIC_ZAP);
new_space = buf->space * 2;
- while (new_space - buf->len - 1 < len) {
+ while (new_space - buf->len < len) {
if (new_space > SIZE_MAX / 2)
goto error_exit;
new_space *= 2;
@@ -90,7 +90,6 @@ ensure_space(struct k5buf *buf, size_t len)
if (new_data == NULL)
goto error_exit;
memcpy(new_data, buf->data, buf->len);
- new_data[buf->len] = '\0';
zap(buf->data, buf->len);
free(buf->data);
} else {
@@ -112,14 +111,13 @@ error_exit:
}
void
-k5_buf_init_fixed(struct k5buf *buf, char *data, size_t space)
+k5_buf_init_fixed(struct k5buf *buf, void *data, size_t space)
{
assert(space > 0);
buf->buftype = K5BUF_FIXED;
buf->data = data;
buf->space = space;
buf->len = 0;
- *endptr(buf) = '\0';
}
void
@@ -133,7 +131,6 @@ k5_buf_init_dynamic(struct k5buf *buf)
return;
}
buf->len = 0;
- *endptr(buf) = '\0';
}
void
@@ -158,7 +155,6 @@ k5_buf_add_len(struct k5buf *buf, const void *data, size_t len)
if (len > 0)
memcpy(endptr(buf), data, len);
buf->len += len;
- *endptr(buf) = '\0';
}
void
@@ -195,7 +191,7 @@ k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
if (r >= 0) {
/* snprintf correctly told us how much space is required. */
- if (!ensure_space(buf, r))
+ if (!ensure_space(buf, r + 1))
return;
remaining = buf->space - buf->len;
r = vsnprintf(endptr(buf), remaining, fmt, ap);
@@ -214,8 +210,8 @@ k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
return;
}
if (ensure_space(buf, r)) {
- /* Copy the temporary string into buf, including terminator. */
- memcpy(endptr(buf), tmp, r + 1);
+ /* Copy the temporary string into buf. */
+ memcpy(endptr(buf), tmp, r);
buf->len += r;
}
if (buf->buftype == K5BUF_DYNAMIC_ZAP)
@@ -233,13 +229,21 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
va_end(ap);
}
+char *
+k5_buf_cstring(struct k5buf *buf)
+{
+ if (!ensure_space(buf, 1))
+ return NULL;
+ *endptr(buf) = '\0';
+ return buf->data;
+}
+
void *
k5_buf_get_space(struct k5buf *buf, size_t len)
{
if (!ensure_space(buf, len))
return NULL;
buf->len += len;
- *endptr(buf) = '\0';
return endptr(buf) - len;
}
@@ -250,7 +254,6 @@ k5_buf_truncate(struct k5buf *buf, size_t len)
return;
assert(len <= buf->len);
buf->len = len;
- *endptr(buf) = '\0';
}
int
diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
index 0bafe1c84..015802496 100644
--- a/src/util/support/libkrb5support-fixed.exports
+++ b/src/util/support/libkrb5support-fixed.exports
@@ -8,6 +8,7 @@ k5_buf_add
k5_buf_add_len
k5_buf_add_fmt
k5_buf_add_vfmt
+k5_buf_cstring
k5_buf_get_space
k5_buf_truncate
k5_buf_status
diff --git a/src/util/support/t_k5buf.c b/src/util/support/t_k5buf.c
index ba86851dc..734b2720c 100644
--- a/src/util/support/t_k5buf.c
+++ b/src/util/support/t_k5buf.c
@@ -50,7 +50,6 @@ check_buf(struct k5buf *buf, const char *name)
} else {
fail_if(buf->space == 0, name);
fail_if(buf->len >= buf->space, name);
- fail_if(((char *)buf->data)[buf->len] != 0, name);
}
}
@@ -65,14 +64,14 @@ test_basic()
k5_buf_add_len(&buf, "world", 5);
check_buf(&buf, "basic fixed");
fail_if(buf.data == NULL || buf.len != 11, "basic fixed");
- fail_if(strcmp(buf.data, "Hello world") != 0, "basic fixed");
+ fail_if(memcmp(buf.data, "Hello world", 11) != 0, "basic fixed");
k5_buf_init_dynamic(&buf);
k5_buf_add_len(&buf, "Hello", 5);
k5_buf_add(&buf, " world");
check_buf(&buf, "basic dynamic");
fail_if(buf.data == NULL || buf.len != 11, "basic dynamic");
- fail_if(strcmp(buf.data, "Hello world") != 0, "basic dynamic");
+ fail_if(memcmp(buf.data, "Hello world", 11) != 0, "basic dynamic");
k5_buf_free(&buf);
}
@@ -141,7 +140,7 @@ test_overflow()
/* Cause a fixed-sized buffer overflow. */
k5_buf_init_fixed(&buf, storage, sizeof(storage));
k5_buf_add(&buf, "12345");
- k5_buf_add(&buf, "12345");
+ k5_buf_add(&buf, "123456");
check_buf(&buf, "overflow 1");
fail_if(buf.buftype != K5BUF_ERROR, "overflow 1");
@@ -161,7 +160,7 @@ test_error()
/* Cause an overflow and then perform actions afterwards. */
k5_buf_init_fixed(&buf, storage, sizeof(storage));
- k5_buf_add(&buf, "1");
+ k5_buf_add(&buf, "12");
fail_if(buf.buftype != K5BUF_ERROR, "error");
check_buf(&buf, "error");
k5_buf_add(&buf, "test");
@@ -184,7 +183,7 @@ test_truncate()
k5_buf_truncate(&buf, 7);
check_buf(&buf, "truncate");
fail_if(buf.data == NULL || buf.len != 7, "truncate");
- fail_if(strcmp(buf.data, "abcdefg") != 0, "truncate");
+ fail_if(memcmp(buf.data, "abcdefg", 7) != 0, "truncate");
k5_buf_free(&buf);
}
@@ -222,7 +221,7 @@ test_fmt()
k5_buf_add_fmt(&buf, " %d ", 3);
check_buf(&buf, "fmt 1");
fail_if(buf.data == NULL || buf.len != 6, "fmt 1");
- fail_if(strcmp(buf.data, "foo 3 ") != 0, "fmt 1");
+ fail_if(memcmp(buf.data, "foo 3 ", 6) != 0, "fmt 1");
/* Overflow the same buffer with formatted text. */
k5_buf_add_fmt(&buf, "%d%d%d%d", 1, 2, 3, 4);
@@ -235,14 +234,14 @@ test_fmt()
k5_buf_add_fmt(&buf, " %d ", 3);
check_buf(&buf, "fmt 3");
fail_if(buf.data == NULL || buf.len != 6, "fmt 3");
- fail_if(strcmp(buf.data, "foo 3 ") != 0, "fmt 3");
+ fail_if(memcmp(buf.data, "foo 3 ", 6) != 0, "fmt 3");
/* Format more text into the same buffer, causing a big resize. */
k5_buf_add_fmt(&buf, "%s", data);
check_buf(&buf, "fmt 4");
fail_if(buf.space != 2048, "fmt 4");
fail_if(buf.data == NULL || buf.len != 1029, "fmt 4");
- fail_if(strcmp((char *)buf.data + 6, data) != 0, "fmt 4");
+ fail_if(memcmp((char *)buf.data + 6, data, 1023) != 0, "fmt 4");
k5_buf_free(&buf);
}
diff --git a/src/util/support/utf8_conv.c b/src/util/support/utf8_conv.c
index 5ddaa2d93..926a3c8a5 100644
--- a/src/util/support/utf8_conv.c
+++ b/src/util/support/utf8_conv.c
@@ -191,8 +191,8 @@ k5_utf16le_to_utf8(const uint8_t *utf16bytes, size_t nbytes, char **utf8_out)
if (in.status)
goto invalid;
- *utf8_out = buf.data;
- return 0;
+ *utf8_out = k5_buf_cstring(&buf);
+ return (*utf8_out == NULL) ? ENOMEM : 0;
invalid:
k5_buf_free(&buf);