From: Greg Hudson Date: Wed, 2 Jul 2014 16:03:54 +0000 (-0400) Subject: Modify k5buf interfaces for easier use X-Git-Tag: krb5-1.13-alpha1~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=651f3af251d172361a954f55f2d87561ae42c2d0;p=thirdparty%2Fkrb5.git Modify k5buf interfaces for easier use Make struct k5buf less opaque and get rid of k5buf-int.h. Make it easy to initialize a k5buf in an error state so that it can be freed in a cleanup handler. Add a function k5_buf_status which returns 0 or ENOMEM. Remove k5_buf_data and k5_buf_len. Rename k5_free_buf to k5_buf_free. Adjust all callers to match. --- diff --git a/src/clients/ksu/authorization.c b/src/clients/ksu/authorization.c index 7f393b8d5c..90aafbd759 100644 --- a/src/clients/ksu/authorization.c +++ b/src/clients/ksu/authorization.c @@ -518,11 +518,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"); - *err_out = k5_buf_data(&buf); - if (*err_out == NULL) { + if (k5_buf_status(&buf) != 0) { perror(prog_name); exit(1); } + *err_out = buf.data; } diff --git a/src/include/k5-buf.h b/src/include/k5-buf.h index da10fd9f4d..f3207bd09a 100644 --- a/src/include/k5-buf.h +++ b/src/include/k5-buf.h @@ -27,62 +27,47 @@ #ifndef K5_BUF_H #define K5_BUF_H -#if defined(_MSDOS) || defined(_WIN32) -#include -#endif -#ifndef KRB5_CALLCONV -#define KRB5_CALLCONV -#define KRB5_CALLCONV_C -#endif - #include #include -#ifndef _WIN32 -#include -#endif /* * The k5buf module is intended to allow multi-step string construction in a * 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 if the fixed buffer runs out of room, the error will be discovered when - * the caller retrieves the C string value or checks the length of the - * resulting buffer. + * 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. * - * k5buf structures are stack-allocated, but are intended to be opaque, so do - * not access the fields directly. This is a tool, not a way of life, so do - * not put k5buf structure pointers into the public API or into significant - * internal APIs. + * 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 + * of a buffer (they will be NULL/0 if the buffer is in an error state), but do + * not change them. */ -/* - * We must define the k5buf structure here to allow stack allocation. The - * structure is intended to be opaque, so the fields have funny names. - */ +/* Buffer type values */ +enum k5buftype { K5BUF_ERROR, K5BUF_FIXED, K5BUF_DYNAMIC }; + struct k5buf { - int xx_buftype; - char *xx_data; - size_t xx_space; - size_t xx_len; + enum k5buftype buftype; + void *data; + size_t space; + size_t len; }; +#define EMPTY_K5BUF { K5BUF_ERROR } + /* 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); -/* Initialize a k5buf using an internally allocated dynamic buffer. The - * buffer contents must be freed with k5_free_buf. */ +/* Initialize a k5buf using an internally allocated dynamic buffer. */ void k5_buf_init_dynamic(struct k5buf *buf); /* Add a C string to BUF. */ void k5_buf_add(struct k5buf *buf, const char *data); -/* - * Add a counted set of bytes to BUF. It is okay for DATA[0..LEN-1] - * to contain null bytes if you are prepared to deal with that in the - * output (use k5_buf_len to retrieve the length of the output). - */ -void k5_buf_add_len(struct k5buf *buf, const char *data, size_t len); +/* 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. */ void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) @@ -99,36 +84,16 @@ void *k5_buf_get_space(struct k5buf *buf, size_t len); * length, or an assertion failure will result. */ void k5_buf_truncate(struct k5buf *buf, size_t len); -/* - * Retrieve the byte array value of BUF, or NULL if there has been an - * allocation failure or the fixed buffer ran out of room. - * - * The byte array will be a C string unless binary data was added with - * k5_buf_add_len; it will be null-terminated regardless. Modifying the byte - * array does not invalidate the buffer, as long as its length is not changed. - * - * For a fixed buffer, the return value will always be equal to the passed-in - * value of DATA at initialization time if it is not NULL. - * - * For a dynamic buffer, any buffer modification operation except - * k5_buf_truncate may invalidate the byte array address. - */ -char *k5_buf_data(struct k5buf *buf); - -/* - * Retrieve the length of BUF, or -1 if there has been an allocation failure or - * the fixed buffer ran out of room. The length is equal to - * strlen(k5_buf_data(buf)) unless binary data was added with k5_buf_add_len. - */ -ssize_t k5_buf_len(struct k5buf *buf); +/* Return ENOMEM if buf is in an error state, 0 otherwise. */ +int k5_buf_status(struct k5buf *buf); /* * Free the storage used in the dynamic buffer BUF. The caller may choose to - * take responsibility for freeing the return value of k5_buf_data instead of - * using this function. If BUF is a fixed buffer, an assertion failure will - * result. It is unnecessary (though harmless) to free a buffer after an error - * is detected; the storage will already have been freed in that case. + * take responsibility for freeing the data pointer instead of using this + * function. If BUF is a fixed buffer, an assertion failure will result. + * Freeing a buffer in the error state, a buffer initialized with EMPTY_K5BUF, + * or a zeroed k5buf structure is a no-op. */ -void k5_free_buf(struct k5buf *buf); +void k5_buf_free(struct k5buf *buf); #endif /* K5_BUF_H */ diff --git a/src/lib/crypto/crypto_tests/t_hmac.c b/src/lib/crypto/crypto_tests/t_hmac.c index 65efa604fe..8961380eaa 100644 --- a/src/lib/crypto/crypto_tests/t_hmac.c +++ b/src/lib/crypto/crypto_tests/t_hmac.c @@ -250,7 +250,7 @@ static void test_hmac() k5_buf_add(&buf, "0x"); for (j = 0; j < out.length; j++) k5_buf_add_fmt(&buf, "%02x", 0xff & outbuf[j]); - if (k5_buf_data(&buf) == NULL) + if (k5_buf_status(&buf) != 0) abort(); if (strcmp(stroutbuf, md5tests[i].hexdigest)) { printf("*** CHECK FAILED!\n" diff --git a/src/lib/crypto/krb/cf2.c b/src/lib/crypto/krb/cf2.c index 5eec1540f6..a0654b6b41 100644 --- a/src/lib/crypto/krb/cf2.c +++ b/src/lib/crypto/krb/cf2.c @@ -59,12 +59,11 @@ prf_plus(krb5_context context, krb5_keyblock *k, const char *pepper, buffer = k5calloc(iterations, prflen, &retval); if (retval) goto cleanup; - if (k5_buf_len(&prf_inbuf) == -1) { - retval = ENOMEM; + retval = k5_buf_status(&prf_inbuf); + if (retval) goto cleanup; - } - in_data.length = (krb5_int32)k5_buf_len(&prf_inbuf); - in_data.data = k5_buf_data(&prf_inbuf); + in_data.length = prf_inbuf.len; + in_data.data = prf_inbuf.data; out_data.length = prflen; out_data.data = buffer; @@ -82,7 +81,7 @@ prf_plus(krb5_context context, krb5_keyblock *k, const char *pepper, cleanup: free(buffer); - k5_free_buf(&prf_inbuf); + k5_buf_free(&prf_inbuf); return retval; } diff --git a/src/lib/gssapi/generic/gssapiP_generic.h b/src/lib/gssapi/generic/gssapiP_generic.h index 5e321867c5..686a21772d 100644 --- a/src/lib/gssapi/generic/gssapiP_generic.h +++ b/src/lib/gssapi/generic/gssapiP_generic.h @@ -273,13 +273,18 @@ k5buf_to_gss(OM_uint32 *minor, gss_buffer_t output_buffer) { OM_uint32 status = GSS_S_COMPLETE; - char *bp = k5_buf_data(input_k5buf); - output_buffer->length = k5_buf_len(input_k5buf); + + if (k5_buf_status(input_k5buf) != 0) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + output_buffer->length = input_k5buf->len; #if defined(_WIN32) || defined(DEBUG_GSSALLOC) if (output_buffer->length > 0) { output_buffer->value = gssalloc_malloc(output_buffer->length); if (output_buffer->value) { - memcpy(output_buffer->value, bp, output_buffer->length); + memcpy(output_buffer->value, input_k5buf->data, + output_buffer->length); } else { status = GSS_S_FAILURE; *minor = ENOMEM; @@ -287,13 +292,10 @@ k5buf_to_gss(OM_uint32 *minor, } else { output_buffer->value = NULL; } - k5_free_buf(input_k5buf); + k5_buf_free(input_k5buf); #else - output_buffer->value = bp; - /* - * it would be nice to invalidate input_k5buf here - * but there is no api for that currently... - */ + output_buffer->value = input_k5buf->data; + memset(input_k5buf, 0, sizeof(*input_k5buf)); #endif return status; } diff --git a/src/lib/gssapi/generic/oid_ops.c b/src/lib/gssapi/generic/oid_ops.c index 1229f3842b..5ad02fceca 100644 --- a/src/lib/gssapi/generic/oid_ops.c +++ b/src/lib/gssapi/generic/oid_ops.c @@ -276,10 +276,6 @@ generic_gss_oid_to_str(OM_uint32 *minor_status, } } k5_buf_add_len(&buf, "}\0", 2); - if (k5_buf_data(&buf) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } return k5buf_to_gss(minor_status, &buf, oid_str); } diff --git a/src/lib/gssapi/mechglue/g_export_cred.c b/src/lib/gssapi/mechglue/g_export_cred.c index 16d1ebef4c..8f5fe4ad5a 100644 --- a/src/lib/gssapi/mechglue/g_export_cred.c +++ b/src/lib/gssapi/mechglue/g_export_cred.c @@ -106,13 +106,9 @@ gss_export_cred(OM_uint32 * minor_status, gss_cred_id_t cred_handle, gss_release_buffer(&tmpmin, &mech_token); } - if (k5_buf_data(&buf) == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } return k5buf_to_gss(minor_status, &buf, token); error: - k5_free_buf(&buf); + k5_buf_free(&buf); return status; } diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index 205333be4a..db45d13c1a 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -66,7 +66,7 @@ krb5_aprof_init(char *fname, char *envname, krb5_pointer *acontextp) krb5_error_code ret; profile_t profile; const char *kdc_config; - char *profile_path, **filenames; + char **filenames; int i; struct k5buf buf; @@ -79,17 +79,16 @@ krb5_aprof_init(char *fname, char *envname, krb5_pointer *acontextp) if (kdc_config) k5_buf_add(&buf, kdc_config); for (i = 0; filenames[i] != NULL; i++) { - if (k5_buf_len(&buf) > 0) + if (buf.len > 0) k5_buf_add(&buf, ":"); k5_buf_add(&buf, filenames[i]); } krb5_free_config_files(filenames); - profile_path = k5_buf_data(&buf); - if (profile_path == NULL) + if (k5_buf_status(&buf) != 0) return ENOMEM; profile = (profile_t) NULL; - ret = profile_init_path(profile_path, &profile); - free(profile_path); + ret = profile_init_path(buf.data, &profile); + k5_buf_free(&buf); if (ret) return ret; *acontextp = profile; diff --git a/src/lib/kadm5/str_conv.c b/src/lib/kadm5/str_conv.c index e8de91520f..216b580bd8 100644 --- a/src/lib/kadm5/str_conv.c +++ b/src/lib/kadm5/str_conv.c @@ -187,14 +187,14 @@ krb5_flags_to_string(flags, sep, buffer, buflen) /* Blast through the table matching all we can */ for (i=0; i 0) + if (buf.len > 0) k5_buf_add(&buf, sepstring); k5_buf_add(&buf, _(flags_table[i].fl_output)); /* Keep track of what we matched */ pflags |= flags_table[i].fl_flags; } } - if (k5_buf_data(&buf) == NULL) + if (k5_buf_status(&buf) != 0) return(ENOMEM); /* See if there's any leftovers */ diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index 7541b1ec45..7c82399b78 100644 --- a/src/lib/kdb/kdb5.c +++ b/src/lib/kdb/kdb5.c @@ -2034,10 +2034,9 @@ krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry, { krb5_error_code code; const char *pos, *end, *mapkey, *mapval; - struct k5buf buf; + struct k5buf buf = EMPTY_K5BUF; krb5_boolean found = FALSE; krb5_tl_data tl_data; - ssize_t len; /* Copy the current mapping to buf, updating key with value if found. */ code = begin_attrs(context, entry, &pos, &end); @@ -2063,17 +2062,20 @@ krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry, k5_buf_add_len(&buf, value, strlen(value) + 1); } - len = k5_buf_len(&buf); - if (len == -1) + if (k5_buf_status(&buf) != 0) return ENOMEM; - if (len > 65535) - return KRB5_KDB_STRINGS_TOOLONG; + if (buf.len > 65535) { + code = KRB5_KDB_STRINGS_TOOLONG; + goto cleanup; + } tl_data.tl_data_type = KRB5_TL_STRING_ATTRS; - tl_data.tl_data_contents = (krb5_octet *)k5_buf_data(&buf); - tl_data.tl_data_length = len; + tl_data.tl_data_contents = buf.data; + tl_data.tl_data_length = buf.len; code = krb5_dbe_update_tl_data(context, entry, &tl_data); - k5_free_buf(&buf); + +cleanup: + k5_buf_free(&buf); return code; } diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c index 3f6443f681..2407851446 100644 --- a/src/lib/krb5/ccache/cc_file.c +++ b/src/lib/krb5/ccache/cc_file.c @@ -402,7 +402,6 @@ read_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) krb5_error_code ret; struct k5buf buf; size_t maxsize; - unsigned char *bytes; *princ = NULL; k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock); @@ -415,17 +414,15 @@ read_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) ret = load_principal(context, id, maxsize, &buf); if (ret) goto cleanup; - bytes = (unsigned char *)k5_buf_data(&buf); - if (bytes == NULL) { - ret = ENOMEM; + ret = k5_buf_status(&buf); + if (ret) goto cleanup; - } /* Unmarshal it from buf into princ. */ - ret = k5_unmarshal_princ(bytes, k5_buf_len(&buf), version(id), princ); + ret = k5_unmarshal_princ(buf.data, buf.len, version(id), princ); cleanup: - k5_free_buf(&buf); + k5_buf_free(&buf); return ret; } @@ -1092,7 +1089,6 @@ fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, fcc_data *data = id->data; struct k5buf buf; size_t maxsize; - unsigned char *bytes; memset(creds, 0, sizeof(*creds)); k5_cc_mutex_lock(context, &data->lock); @@ -1111,18 +1107,16 @@ fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, ret = load_cred(context, id, maxsize, &buf); if (ret) goto cleanup; - bytes = (unsigned char *)k5_buf_data(&buf); - if (bytes == NULL) { - ret = ENOMEM; + ret = k5_buf_status(&buf); + if (ret) goto cleanup; - } /* Unmarshal it from buf into creds. */ fcursor->pos = fcc_lseek(data, 0, SEEK_CUR); - ret = k5_unmarshal_cred(bytes, k5_buf_len(&buf), version(id), creds); + ret = k5_unmarshal_cred(buf.data, buf.len, version(id), creds); cleanup: - k5_free_buf(&buf); + k5_buf_free(&buf); MAYBE_CLOSE(context, id, ret); k5_cc_mutex_unlock(context, &data->lock); return ret; diff --git a/src/lib/krb5/ccache/ccmarshal.c b/src/lib/krb5/ccache/ccmarshal.c index c27b43f1c9..d190577d77 100644 --- a/src/lib/krb5/ccache/ccmarshal.c +++ b/src/lib/krb5/ccache/ccmarshal.c @@ -449,10 +449,10 @@ k5_marshal_cred(krb5_creds *creds, int version, unsigned char **bytes_out, marshal_authdata(&buf, version, creds->authdata); put_data(&buf, version, &creds->ticket); put_data(&buf, version, &creds->second_ticket); - if (k5_buf_data(&buf) == NULL) + if (k5_buf_status(&buf) != 0) return ENOMEM; - *bytes_out = (unsigned char *)k5_buf_data(&buf); - *len_out = k5_buf_len(&buf); + *bytes_out = buf.data; + *len_out = buf.len; return 0; } @@ -468,9 +468,9 @@ k5_marshal_princ(krb5_principal princ, int version, unsigned char **bytes_out, *len_out = 0; k5_buf_init_dynamic(&buf); marshal_princ(&buf, version, princ); - if (k5_buf_data(&buf) == NULL) + if (k5_buf_status(&buf) != 0) return ENOMEM; - *bytes_out = (unsigned char *)k5_buf_data(&buf); - *len_out = k5_buf_len(&buf); + *bytes_out = buf.data; + *len_out = buf.len; return 0; } diff --git a/src/lib/krb5/krb/chpw.c b/src/lib/krb5/krb/chpw.c index 463ce643e5..b8010b36fc 100644 --- a/src/lib/krb5/krb/chpw.c +++ b/src/lib/krb5/krb/chpw.c @@ -384,7 +384,7 @@ struct ad_policy_info { static void add_spaces(struct k5buf *buf) { - if (k5_buf_len(buf) > 0) + if (buf->len > 0) k5_buf_add(buf, " "); } @@ -394,7 +394,6 @@ decode_ad_policy_info(const krb5_data *data, char **msg_out) struct ad_policy_info policy; uint64_t password_days; const char *p; - char *msg; struct k5buf buf; *msg_out = NULL; @@ -465,14 +464,13 @@ decode_ad_policy_info(const krb5_data *data, char **msg_out) (int)password_days); } - msg = k5_buf_data(&buf); - if (msg == NULL) + if (k5_buf_status(&buf) != 0) return ENOMEM; - if (*msg != '\0') - *msg_out = msg; + if (buf.len > 0) + *msg_out = buf.data; else - free(msg); + k5_buf_free(&buf); return 0; } diff --git a/src/lib/krb5/krb/srv_rcache.c b/src/lib/krb5/krb/srv_rcache.c index 1b0a91a281..692c853a29 100644 --- a/src/lib/krb5/krb/srv_rcache.c +++ b/src/lib/krb5/krb/srv_rcache.c @@ -35,10 +35,10 @@ krb5_get_server_rcache(krb5_context context, const krb5_data *piece, krb5_rcache *rcptr) { krb5_rcache rcache = 0; - char *cachename = 0, *cachetype; + char *cachetype; krb5_error_code retval; unsigned int i; - struct k5buf buf; + struct k5buf buf = EMPTY_K5BUF; #ifdef HAVE_GETEUID unsigned long uid = geteuid(); #endif @@ -63,11 +63,10 @@ krb5_get_server_rcache(krb5_context context, const krb5_data *piece, k5_buf_add_fmt(&buf, "_%lu", uid); #endif - cachename = k5_buf_data(&buf); - if (cachename == NULL) + if (k5_buf_status(&buf) != 0) return ENOMEM; - retval = krb5_rc_resolve_full(context, &rcache, cachename); + retval = krb5_rc_resolve_full(context, &rcache, buf.data); if (retval) goto cleanup; @@ -83,7 +82,6 @@ krb5_get_server_rcache(krb5_context context, const krb5_data *piece, cleanup: if (rcache) krb5_rc_close(context, rcache); - if (cachename) - free(cachename); + k5_buf_free(&buf); return retval; } diff --git a/src/lib/krb5/os/dnsglue.c b/src/lib/krb5/os/dnsglue.c index fcb99ff7cf..7d25fee070 100644 --- a/src/lib/krb5/os/dnsglue.c +++ b/src/lib/krb5/os/dnsglue.c @@ -389,11 +389,10 @@ k5_try_realm_txt_rr(krb5_context context, const char *prefix, const char *name, the local domain or domain search lists to be expanded. */ - len = k5_buf_len(&buf); - if (len > 0 && host[len - 1] != '.') + if (buf.len > 0 && host[buf.len - 1] != '.') k5_buf_add(&buf, "."); } - if (k5_buf_data(&buf) == NULL) + if (k5_buf_status(&buf) != 0) return KRB5_ERR_HOST_REALM_UNKNOWN; ret = krb5int_dns_init(&ds, host, C_IN, T_TXT); if (ret < 0) { diff --git a/src/lib/krb5/os/dnssrv.c b/src/lib/krb5/os/dnssrv.c index 33ee0e7e9b..c41b0d80d5 100644 --- a/src/lib/krb5/os/dnssrv.c +++ b/src/lib/krb5/os/dnssrv.c @@ -59,7 +59,7 @@ krb5int_make_srv_query_realm(const krb5_data *realm, { const unsigned char *p = NULL, *base = NULL; char host[MAXDNAME]; - int size, ret, rdlen, nlen, len; + int size, ret, rdlen, nlen; unsigned short priority, weight, port; struct krb5int_dns_state *ds = NULL; struct k5buf buf; @@ -93,11 +93,10 @@ krb5int_make_srv_query_realm(const krb5_data *realm, a search on the prefix alone then the intention is to allow the local domain or domain search lists to be expanded. */ - len = k5_buf_len(&buf); - if (len > 0 && host[len - 1] != '.') + if (buf.len > 0 && host[buf.len - 1] != '.') k5_buf_add(&buf, "."); - if (k5_buf_data(&buf) == NULL) + if (k5_buf_status(&buf) != 0) return 0; #ifdef TEST diff --git a/src/lib/krb5/os/expand_path.c b/src/lib/krb5/os/expand_path.c index 4646c54525..6142b3bbd5 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, *path, **extra_tokens = NULL; + char *tok_begin, *tok_end, *tok_val, **extra_tokens = NULL; const char *path_left; size_t nargs = 0, i; va_list ap; @@ -517,26 +517,25 @@ k5_expand_path_tokens_extra(krb5_context context, const char *path_in, path_left = tok_end + 1; } - path = k5_buf_data(&buf); - if (path == NULL) { - ret = ENOMEM; + ret = k5_buf_status(&buf); + if (ret) goto cleanup; - } + #ifdef _WIN32 /* Also deal with slashes. */ { char *p; - for (p = path; *p != '\0'; p++) { + for (p = buf.data; *p != '\0'; p++) { if (*p == '/') *p = '\\'; } } #endif - *path_out = path; + *path_out = buf.data; + memset(&buf, 0, sizeof(buf)); cleanup: - if (*path_out == NULL) - k5_free_buf(&buf); + k5_buf_free(&buf); free_extra_tokens(extra_tokens); return 0; } diff --git a/src/lib/krb5/os/localauth_rule.c b/src/lib/krb5/os/localauth_rule.c index 584dcba540..852210825d 100644 --- a/src/lib/krb5/os/localauth_rule.c +++ b/src/lib/krb5/os/localauth_rule.c @@ -130,8 +130,10 @@ do_replacement(const char *regstr, const char *repl, krb5_boolean doall, } regfree(&re); k5_buf_add(&buf, instr); - *outstr = k5_buf_data(&buf); - return *outstr == NULL ? ENOMEM : 0; + if (k5_buf_status(&buf) != 0) + return ENOMEM; + *outstr = buf.data; + return 0; } /* @@ -207,7 +209,7 @@ aname_get_selstring(krb5_context context, krb5_const_principal aname, const char **contextp, char **selstring_out) { const char *current; - char *end, *str; + char *end; long num_comps, ind; const krb5_data *datap; struct k5buf selstring; @@ -257,16 +259,15 @@ aname_get_selstring(krb5_context context, krb5_const_principal aname, /* Check that we hit a ']' and not the end of the string. */ if (*current != ']') { - k5_free_buf(&selstring); + k5_buf_free(&selstring); return KRB5_CONFIG_BADFORMAT; } - str = k5_buf_data(&selstring); - if (str == NULL) + if (k5_buf_status(&selstring) != 0) return ENOMEM; *contextp = current + 1; - *selstring_out = str; + *selstring_out = selstring.data; return 0; } diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c index 224224077e..3b3b438ce6 100644 --- a/src/lib/krb5/os/sendto_kdc.c +++ b/src/lib/krb5/os/sendto_kdc.c @@ -558,13 +558,13 @@ make_proxy_request(struct conn_state *state, const krb5_data *realm, k5_buf_add(&buf, "Content-type: application/kerberos\r\n"); k5_buf_add_fmt(&buf, "Content-Length: %d\r\n\r\n", encoded_pm->length); k5_buf_add_len(&buf, encoded_pm->data, encoded_pm->length); - if (k5_buf_data(&buf) == NULL) { + if (k5_buf_status(&buf) != 0) { ret = ENOMEM; goto cleanup; } - *req_out = k5_buf_data(&buf); - *len_out = k5_buf_len(&buf); + *req_out = buf.data; + *len_out = buf.len; cleanup: krb5_free_data_contents(NULL, &pm.kerb_message); diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c index 5fbe573a11..83c8d4db87 100644 --- a/src/lib/krb5/os/trace.c +++ b/src/lib/krb5/os/trace.c @@ -305,7 +305,7 @@ trace_format(krb5_context context, const char *fmt, va_list ap) creds->client, creds->server); } } - return k5_buf_data(&buf); + return buf.data; } /* Allows trace_format formatters to be represented in terms of other diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c index 8f517d0c8b..2fb6aa00f5 100644 --- a/src/lib/krb5/rcache/rc_dfl.c +++ b/src/lib/krb5/rcache/rc_dfl.c @@ -642,11 +642,10 @@ krb5_rc_io_store(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep) { size_t clientlen, serverlen; - ssize_t buflen; unsigned int len; krb5_error_code ret; struct k5buf buf, extbuf; - char *bufptr, *extstr; + char *extstr; clientlen = strlen(rep->client); serverlen = strlen(rep->server); @@ -663,9 +662,9 @@ krb5_rc_io_store(krb5_context context, struct dfl_data *t, k5_buf_add_fmt(&extbuf, "HASH:%s %lu:%s %lu:%s", rep->msghash, (unsigned long)clientlen, rep->client, (unsigned long)serverlen, rep->server); - extstr = k5_buf_data(&extbuf); - if (!extstr) + if (k5_buf_status(&extbuf) != 0) return KRB5_RC_MALLOC; + extstr = extbuf.data; /* * Put the extension value into the server field of a @@ -693,13 +692,11 @@ krb5_rc_io_store(krb5_context context, struct dfl_data *t, k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec)); k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime)); - bufptr = k5_buf_data(&buf); - buflen = k5_buf_len(&buf); - if (bufptr == NULL || buflen < 0) + if (k5_buf_status(&buf) != 0) return KRB5_RC_MALLOC; - ret = krb5_rc_io_write(context, &t->d, bufptr, buflen); - k5_free_buf(&buf); + ret = krb5_rc_io_write(context, &t->d, buf.data, buf.len); + k5_buf_free(&buf); return ret; } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c index 3f3efdcb5e..af0eaf1ce5 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c @@ -422,9 +422,9 @@ 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); - *o_princ_name = k5_buf_data(&buf); - if (!*o_princ_name) + if (k5_buf_status(&buf) != 0) return ENOMEM; + *o_princ_name = buf.data; } return 0; } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c index 7858a555e4..e9fb3fa023 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 k5_buf_data(&buf); + return buf.data; } static int diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index 02261637f2..c849f87365 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -2173,11 +2173,11 @@ reassemble_pkcs11_name(PLArenaPool *pool, pkinit_identity_opts *idopts) k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "", (long)idopts->slotid); } - if (k5_buf_len(&buf) >= 0) - ret = PORT_ArenaStrdup(pool, k5_buf_data(&buf)); + if (k5_buf_status(&buf) == 0) + ret = PORT_ArenaStrdup(pool, buf.data); else ret = NULL; - k5_free_buf(&buf); + k5_buf_free(&buf); return ret; } @@ -2209,11 +2209,11 @@ reassemble_pkcs11_identity(PLArenaPool *pool, pkinit_identity_opts *idopts, if (tokenname != NULL) k5_buf_add_fmt(&buf, "%stoken=%s", n++ ? ":" : "", tokenname); - if (k5_buf_len(&buf) >= 0) - ret = PORT_ArenaStrdup(pool, k5_buf_data(&buf)); + if (k5_buf_status(&buf) == 0) + ret = PORT_ArenaStrdup(pool, buf.data); else ret = NULL; - k5_free_buf(&buf); + k5_buf_free(&buf); return ret; } diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c index 246bc1b938..4d9b5e50ca 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c @@ -4450,11 +4450,11 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts) k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "", (long)idopts->slotid); } - if (k5_buf_len(&buf) >= 0) - ret = strdup(k5_buf_data(&buf)); + if (k5_buf_status(&buf) == 0) + ret = strdup(buf.data); else ret = NULL; - k5_free_buf(&buf); + k5_buf_free(&buf); return ret; } diff --git a/src/util/gss-kernel-lib/t_kgss_user.c b/src/util/gss-kernel-lib/t_kgss_user.c index 0af9aa6c82..8c67b5dcb1 100644 --- a/src/util/gss-kernel-lib/t_kgss_user.c +++ b/src/util/gss-kernel-lib/t_kgss_user.c @@ -175,9 +175,9 @@ marshal_lucid_context(const gss_krb5_lucid_context_v1_t *lctx, add_lucid_key(&buf, &lctx->cfx_kd.acceptor_subkey); } else abort(); - assert(k5_buf_data(&buf) != NULL); - *data_out = (unsigned char *)k5_buf_data(&buf); - *len_out = k5_buf_len(&buf); + assert(k5_buf_status(&buf) == 0); + *data_out = buf.data; + *len_out = buf.len; } /* Export ctx as a lucid context, marshal it, and write it to fd. */ diff --git a/src/util/support/deps b/src/util/support/deps index 76bdefdcf5..82a2b4e572 100644 --- a/src/util/support/deps +++ b/src/util/support/deps @@ -20,7 +20,7 @@ errors.so errors.po $(OUTPRE)errors.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-thread.h errors.c supp-int.h k5buf.so k5buf.po $(OUTPRE)k5buf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-thread.h k5buf-int.h k5buf.c + $(top_srcdir)/include/k5-thread.h k5buf.c gmt_mktime.so gmt_mktime.po $(OUTPRE)gmt_mktime.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(top_srcdir)/include/k5-gmt_mktime.h \ gmt_mktime.c @@ -53,7 +53,7 @@ mkstemp.so mkstemp.po $(OUTPRE)mkstemp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h mkstemp.c t_k5buf.so t_k5buf.po $(OUTPRE)t_k5buf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-thread.h k5buf-int.h t_k5buf.c + $(top_srcdir)/include/k5-thread.h t_k5buf.c t_unal.so t_unal.po $(OUTPRE)t_unal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ t_unal.c diff --git a/src/util/support/json.c b/src/util/support/json.c index d23267c174..98f6568b24 100644 --- a/src/util/support/json.c +++ b/src/util/support/json.c @@ -696,11 +696,13 @@ k5_json_encode(k5_json_value val, char **json_out) k5_buf_init_dynamic(&buf); ret = encode_value(&buf, val); if (ret) { - k5_free_buf(&buf); + k5_buf_free(&buf); return ret; } - *json_out = k5_buf_data(&buf); - return (*json_out == NULL) ? ENOMEM : 0; + if (k5_buf_status(&buf) != 0) + return ENOMEM; + *json_out = buf.data; + return 0; } /*** JSON decoding ***/ diff --git a/src/util/support/k5buf-int.h b/src/util/support/k5buf-int.h deleted file mode 100644 index 6f2ec19e7c..0000000000 --- a/src/util/support/k5buf-int.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* util/support/k5buf-int.h - Internal declarations for string buffers */ -/* - * Copyright 2008 Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -#ifndef K5BUF_INT_H -#define K5BUF_INT_H - -#include "k5-platform.h" -#include "k5-buf.h" - -/* - * The k5buf structure has funny field names to discourage callers from - * violating the abstraction barrier. Define less funny names for them here. - */ -#define buftype xx_buftype -#define data xx_data -#define space xx_space -#define len xx_len - -#define DYNAMIC_INITIAL_SIZE 128 -#define SPACE_MAX (SIZE_MAX / 2) /* rounds down, since SIZE_MAX is odd */ - -/* Buffer type values. */ -enum { BUFTYPE_FIXED, BUFTYPE_DYNAMIC, BUFTYPE_ERROR }; - -#endif /* K5BUF_INT_H */ diff --git a/src/util/support/k5buf.c b/src/util/support/k5buf.c index c3c81b0b2c..f619f6a489 100644 --- a/src/util/support/k5buf.c +++ b/src/util/support/k5buf.c @@ -30,20 +30,36 @@ * needs to be generated with error tables, after util/et, which builds after * this directory. */ -#include "k5buf-int.h" +#include "k5-platform.h" +#include "k5-buf.h" #include /* * Structure invariants: * - * buftype is BUFTYPE_FIXED, BUFTYPE_DYNAMIC, or BUFTYPE_ERROR - * if buftype is not BUFTYPE_ERROR: + * buftype is K5BUF_FIXED, K5BUF_DYNAMIC, or K5BUF_ERROR + * if buftype is K5BUF_ERROR, the other fields are NULL or 0 + * if buftype is not K5BUF_ERROR: * space > 0 - * space <= floor(SIZE_MAX / 2) (to fit within ssize_t) * len < space * data[len] = '\0' */ +/* Return a character pointer to the current end of buf. */ +static inline char * +endptr(struct k5buf *buf) +{ + return (char *)buf->data + buf->len; +} + +static inline void +set_error(struct k5buf *buf) +{ + buf->buftype = K5BUF_ERROR; + buf->data = NULL; + buf->space = buf->len = 0; +} + /* * Make sure there is room for LEN more characters in BUF, in addition to the * null terminator and what's already in there. Return true on success. On @@ -55,18 +71,19 @@ ensure_space(struct k5buf *buf, size_t len) size_t new_space; char *new_data; - if (buf->buftype == BUFTYPE_ERROR) + if (buf->buftype == K5BUF_ERROR) return 0; if (buf->space - 1 - buf->len >= len) /* Enough room already. */ return 1; - if (buf->buftype == BUFTYPE_FIXED) /* Can't resize a fixed buffer. */ + if (buf->buftype == K5BUF_FIXED) /* Can't resize a fixed buffer. */ goto error_exit; - assert(buf->buftype == BUFTYPE_DYNAMIC); + assert(buf->buftype == K5BUF_DYNAMIC); new_space = buf->space * 2; - while (new_space <= SPACE_MAX && new_space - buf->len - 1 < len) + while (new_space - buf->len - 1 < len) { + if (new_space > SIZE_MAX / 2) + goto error_exit; new_space *= 2; - if (new_space > SPACE_MAX) - goto error_exit; + } new_data = realloc(buf->data, new_space); if (new_data == NULL) goto error_exit; @@ -75,11 +92,9 @@ ensure_space(struct k5buf *buf, size_t len) return 1; error_exit: - if (buf->buftype == BUFTYPE_DYNAMIC) { + if (buf->buftype == K5BUF_DYNAMIC) free(buf->data); - buf->data = NULL; - } - buf->buftype = BUFTYPE_ERROR; + set_error(buf); return 0; } @@ -87,25 +102,25 @@ void k5_buf_init_fixed(struct k5buf *buf, char *data, size_t space) { assert(space > 0); - buf->buftype = BUFTYPE_FIXED; + buf->buftype = K5BUF_FIXED; buf->data = data; buf->space = space; buf->len = 0; - buf->data[0] = '\0'; + *endptr(buf) = '\0'; } void k5_buf_init_dynamic(struct k5buf *buf) { - buf->buftype = BUFTYPE_DYNAMIC; - buf->space = DYNAMIC_INITIAL_SIZE; + buf->buftype = K5BUF_DYNAMIC; + buf->space = 128; buf->data = malloc(buf->space); if (buf->data == NULL) { - buf->buftype = BUFTYPE_ERROR; + set_error(buf); return; } buf->len = 0; - buf->data[0] = '\0'; + *endptr(buf) = '\0'; } void @@ -115,14 +130,14 @@ k5_buf_add(struct k5buf *buf, const char *data) } void -k5_buf_add_len(struct k5buf *buf, const char *data, size_t len) +k5_buf_add_len(struct k5buf *buf, const void *data, size_t len) { if (!ensure_space(buf, len)) return; if (len > 0) - memcpy(buf->data + buf->len, data, len); + memcpy(endptr(buf), data, len); buf->len += len; - buf->data[buf->len] = '\0'; + *endptr(buf) = '\0'; } void @@ -133,26 +148,26 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) size_t remaining; char *tmp; - if (buf->buftype == BUFTYPE_ERROR) + if (buf->buftype == K5BUF_ERROR) return; remaining = buf->space - buf->len; - if (buf->buftype == BUFTYPE_FIXED) { + if (buf->buftype == K5BUF_FIXED) { /* Format the data directly into the fixed buffer. */ va_start(ap, fmt); - r = vsnprintf(buf->data + buf->len, remaining, fmt, ap); + r = vsnprintf(endptr(buf), remaining, fmt, ap); va_end(ap); if (SNPRINTF_OVERFLOW(r, remaining)) - buf->buftype = BUFTYPE_ERROR; + set_error(buf); else buf->len += (unsigned int) r; return; } /* Optimistically format the data directly into the dynamic buffer. */ - assert(buf->buftype == BUFTYPE_DYNAMIC); + assert(buf->buftype == K5BUF_DYNAMIC); va_start(ap, fmt); - r = vsnprintf(buf->data + buf->len, remaining, fmt, ap); + r = vsnprintf(endptr(buf), remaining, fmt, ap); va_end(ap); if (!SNPRINTF_OVERFLOW(r, remaining)) { buf->len += (unsigned int) r; @@ -165,10 +180,10 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) return; remaining = buf->space - buf->len; va_start(ap, fmt); - r = vsnprintf(buf->data + buf->len, remaining, fmt, ap); + r = vsnprintf(endptr(buf), remaining, fmt, ap); va_end(ap); if (SNPRINTF_OVERFLOW(r, remaining)) /* Shouldn't ever happen. */ - buf->buftype = BUFTYPE_ERROR; + k5_buf_free(buf); else buf->len += (unsigned int) r; return; @@ -180,12 +195,12 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) r = vasprintf(&tmp, fmt, ap); va_end(ap); if (r < 0) { - buf->buftype = BUFTYPE_ERROR; + k5_buf_free(buf); return; } if (ensure_space(buf, r)) { /* Copy the temporary string into buf, including terminator. */ - memcpy(buf->data + buf->len, tmp, r + 1); + memcpy(endptr(buf), tmp, r + 1); buf->len += r; } free(tmp); @@ -197,40 +212,32 @@ k5_buf_get_space(struct k5buf *buf, size_t len) if (!ensure_space(buf, len)) return NULL; buf->len += len; - buf->data[buf->len] = '\0'; - return &buf->data[buf->len - len]; + *endptr(buf) = '\0'; + return endptr(buf) - len; } void k5_buf_truncate(struct k5buf *buf, size_t len) { - if (buf->buftype == BUFTYPE_ERROR) + if (buf->buftype == K5BUF_ERROR) return; assert(len <= buf->len); buf->len = len; - buf->data[buf->len] = '\0'; + *endptr(buf) = '\0'; } - -char * -k5_buf_data(struct k5buf *buf) +int +k5_buf_status(struct k5buf *buf) { - return (buf->buftype == BUFTYPE_ERROR) ? NULL : buf->data; -} - -ssize_t -k5_buf_len(struct k5buf *buf) -{ - return (buf->buftype == BUFTYPE_ERROR) ? -1 : (ssize_t) buf->len; + return (buf->buftype == K5BUF_ERROR) ? ENOMEM : 0; } void -k5_free_buf(struct k5buf *buf) +k5_buf_free(struct k5buf *buf) { - if (buf->buftype == BUFTYPE_ERROR) + if (buf->buftype == K5BUF_ERROR) return; - assert(buf->buftype == BUFTYPE_DYNAMIC); + assert(buf->buftype == K5BUF_DYNAMIC); free(buf->data); - buf->data = NULL; - buf->buftype = BUFTYPE_ERROR; + set_error(buf); } diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports index b5ca0b28c5..1aa242803d 100644 --- a/src/util/support/libkrb5support-fixed.exports +++ b/src/util/support/libkrb5support-fixed.exports @@ -8,9 +8,8 @@ k5_buf_add_len k5_buf_add_fmt k5_buf_get_space k5_buf_truncate -k5_buf_data -k5_buf_len -k5_free_buf +k5_buf_status +k5_buf_free k5_set_error k5_vset_error k5_get_error diff --git a/src/util/support/t_k5buf.c b/src/util/support/t_k5buf.c index 5e660d40fe..ba86851dc4 100644 --- a/src/util/support/t_k5buf.c +++ b/src/util/support/t_k5buf.c @@ -24,7 +24,8 @@ * or implied warranty. */ -#include "k5buf-int.h" +#include "k5-platform.h" +#include "k5-buf.h" #include #include @@ -41,47 +42,45 @@ fail_if(int condition, const char *name) static void check_buf(struct k5buf *buf, const char *name) { - fail_if(buf->buftype != BUFTYPE_FIXED && buf->buftype != BUFTYPE_DYNAMIC - && buf->buftype != BUFTYPE_ERROR, name); - if (buf->buftype == BUFTYPE_ERROR) - return; - fail_if(buf->space == 0, name); - fail_if(buf->space > SPACE_MAX, name); - fail_if(buf->len >= buf->space, name); - fail_if(buf->data[buf->len] != 0, name); + fail_if(buf->buftype != K5BUF_FIXED && buf->buftype != K5BUF_DYNAMIC && + buf->buftype != K5BUF_ERROR, name); + if (buf->buftype == K5BUF_ERROR) { + fail_if(buf->data != NULL, name); + fail_if(buf->space != 0 || buf->len != 0, name); + } else { + fail_if(buf->space == 0, name); + fail_if(buf->len >= buf->space, name); + fail_if(((char *)buf->data)[buf->len] != 0, name); + } } static void test_basic() { struct k5buf buf; - char storage[1024], *s; - ssize_t len; + char storage[1024]; k5_buf_init_fixed(&buf, storage, sizeof(storage)); k5_buf_add(&buf, "Hello "); k5_buf_add_len(&buf, "world", 5); check_buf(&buf, "basic fixed"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || strcmp(s, "Hello world") != 0 || len != 11, "basic fixed"); + fail_if(buf.data == NULL || buf.len != 11, "basic fixed"); + fail_if(strcmp(buf.data, "Hello world") != 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"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || strcmp(s, "Hello world") != 0 || len != 11, "basic dynamic"); - k5_free_buf(&buf); + fail_if(buf.data == NULL || buf.len != 11, "basic dynamic"); + fail_if(strcmp(buf.data, "Hello world") != 0, "basic dynamic"); + k5_buf_free(&buf); } static void test_realloc() { struct k5buf buf; - char data[1024], *s; - ssize_t len; + char data[1024]; size_t i; for (i = 0; i < sizeof(data); i++) @@ -93,18 +92,16 @@ test_realloc() k5_buf_add_len(&buf, data, 128); fail_if(buf.space != 256, "realloc 1"); check_buf(&buf, "realloc 1"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 138 || memcmp(s, data, len) != 0, "realloc 1"); + fail_if(buf.data == NULL || buf.len != 138, "realloc 1"); + fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 1"); /* Cause the same buffer to double in size to 512 bytes. */ k5_buf_add_len(&buf, data, 128); fail_if(buf.space != 512, "realloc 2"); check_buf(&buf, "realloc 2"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 266 || memcmp(s, data, len) != 0, "realloc 2"); - k5_free_buf(&buf); + fail_if(buf.data == NULL || buf.len != 266, "realloc 2"); + fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 2"); + k5_buf_free(&buf); /* Cause a buffer to increase from 128 to 512 bytes directly. */ k5_buf_init_dynamic(&buf); @@ -112,10 +109,9 @@ test_realloc() k5_buf_add_len(&buf, data, 256); fail_if(buf.space != 512, "realloc 3"); check_buf(&buf, "realloc 3"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 266 || memcmp(s, data, len) != 0, "realloc 3"); - k5_free_buf(&buf); + fail_if(buf.data == NULL || buf.len != 266, "realloc 3"); + fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 3"); + k5_buf_free(&buf); /* Cause a buffer to increase from 128 to 1024 bytes directly. */ k5_buf_init_dynamic(&buf); @@ -123,60 +119,38 @@ test_realloc() k5_buf_add_len(&buf, data, 512); fail_if(buf.space != 1024, "realloc 4"); check_buf(&buf, "realloc 4"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 522 || memcmp(s, data, len) != 0, "realloc 4"); - k5_free_buf(&buf); - - /* Cause a reallocation to fail by exceeding SPACE_MAX. */ - k5_buf_init_dynamic(&buf); - k5_buf_add_len(&buf, data, 10); - k5_buf_add_len(&buf, NULL, SPACE_MAX); - check_buf(&buf, "realloc 5"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(buf.buftype != BUFTYPE_ERROR || s != NULL || len != -1, - "realloc 5"); - k5_free_buf(&buf); + fail_if(buf.data == NULL || buf.len != 522, "realloc 4"); + fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 4"); + k5_buf_free(&buf); /* Cause a reallocation to fail by integer overflow. */ k5_buf_init_dynamic(&buf); k5_buf_add_len(&buf, data, 100); - k5_buf_add_len(&buf, NULL, SPACE_MAX * 2); - check_buf(&buf, "realloc 6"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(buf.buftype != BUFTYPE_ERROR || s != NULL || len != -1, - "realloc 6"); - k5_free_buf(&buf); + k5_buf_add_len(&buf, NULL, SIZE_MAX); + check_buf(&buf, "realloc 5"); + fail_if(buf.buftype != K5BUF_ERROR, "realloc 5"); + k5_buf_free(&buf); } static void test_overflow() { struct k5buf buf; - char storage[10], *s; - ssize_t len; + char storage[10]; /* Cause a fixed-sized buffer overflow. */ k5_buf_init_fixed(&buf, storage, sizeof(storage)); k5_buf_add(&buf, "12345"); k5_buf_add(&buf, "12345"); check_buf(&buf, "overflow 1"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(buf.buftype != BUFTYPE_ERROR || s != NULL || len != -1, - "overflow 1"); + fail_if(buf.buftype != K5BUF_ERROR, "overflow 1"); /* Cause a fixed-sized buffer overflow with integer overflow. */ k5_buf_init_fixed(&buf, storage, sizeof(storage)); k5_buf_add(&buf, "12345"); - k5_buf_add_len(&buf, NULL, SPACE_MAX * 2); + k5_buf_add_len(&buf, NULL, SIZE_MAX); check_buf(&buf, "overflow 2"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(buf.buftype != BUFTYPE_ERROR || s != NULL || len != -1, - "overflow 2"); + fail_if(buf.buftype != K5BUF_ERROR, "overflow 2"); } static void @@ -188,7 +162,7 @@ test_error() /* Cause an overflow and then perform actions afterwards. */ k5_buf_init_fixed(&buf, storage, sizeof(storage)); k5_buf_add(&buf, "1"); - fail_if(buf.buftype != BUFTYPE_ERROR, "error"); + fail_if(buf.buftype != K5BUF_ERROR, "error"); check_buf(&buf, "error"); k5_buf_add(&buf, "test"); check_buf(&buf, "error"); @@ -196,52 +170,46 @@ test_error() check_buf(&buf, "error"); k5_buf_truncate(&buf, 3); check_buf(&buf, "error"); - fail_if(buf.buftype != BUFTYPE_ERROR, "error"); + fail_if(buf.buftype != K5BUF_ERROR, "error"); } static void test_truncate() { struct k5buf buf; - char *s; - ssize_t len; k5_buf_init_dynamic(&buf); k5_buf_add(&buf, "abcde"); k5_buf_add(&buf, "fghij"); k5_buf_truncate(&buf, 7); check_buf(&buf, "truncate"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 7 || strcmp(s, "abcdefg") != 0, "truncate"); - k5_free_buf(&buf); + fail_if(buf.data == NULL || buf.len != 7, "truncate"); + fail_if(strcmp(buf.data, "abcdefg") != 0, "truncate"); + k5_buf_free(&buf); } static void test_binary() { struct k5buf buf; - char *s, data[] = { 'a', 0, 'b' }; - ssize_t len; + char data[] = { 'a', 0, 'b' }, *s; k5_buf_init_dynamic(&buf); k5_buf_add_len(&buf, data, 3); k5_buf_add_len(&buf, data, 3); check_buf(&buf, "binary"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 6, "binary"); + fail_if(buf.data == NULL || buf.len != 6, "binary"); + s = buf.data; fail_if(s[0] != 'a' || s[1] != 0 || s[2] != 'b', "binary"); fail_if(s[3] != 'a' || s[4] != 0 || s[5] != 'b', "binary"); - k5_free_buf(&buf); + k5_buf_free(&buf); } static void test_fmt() { struct k5buf buf; - char *s, storage[10], data[1024]; - ssize_t len; + char storage[10], data[1024]; size_t i; for (i = 0; i < sizeof(data) - 1; i++) @@ -253,34 +221,29 @@ test_fmt() k5_buf_add(&buf, "foo"); k5_buf_add_fmt(&buf, " %d ", 3); check_buf(&buf, "fmt 1"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 6 || strcmp(s, "foo 3 ") != 0, "fmt 1"); + fail_if(buf.data == NULL || buf.len != 6, "fmt 1"); + fail_if(strcmp(buf.data, "foo 3 ") != 0, "fmt 1"); /* Overflow the same buffer with formatted text. */ k5_buf_add_fmt(&buf, "%d%d%d%d", 1, 2, 3, 4); check_buf(&buf, "fmt 2"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(buf.buftype != BUFTYPE_ERROR || s != NULL || len != -1, "fmt 2"); + fail_if(buf.buftype != K5BUF_ERROR, "fmt 2"); /* Format some text into a non-empty dynamic buffer. */ k5_buf_init_dynamic(&buf); k5_buf_add(&buf, "foo"); k5_buf_add_fmt(&buf, " %d ", 3); check_buf(&buf, "fmt 3"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 6 || strcmp(s, "foo 3 ") != 0, "fmt 3"); + fail_if(buf.data == NULL || buf.len != 6, "fmt 3"); + fail_if(strcmp(buf.data, "foo 3 ") != 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"); - s = k5_buf_data(&buf); - len = k5_buf_len(&buf); - fail_if(!s || len != 1029 || strcmp(s + 6, data) != 0, "fmt 4"); - k5_free_buf(&buf); + fail_if(buf.data == NULL || buf.len != 1029, "fmt 4"); + fail_if(strcmp((char *)buf.data + 6, data) != 0, "fmt 4"); + k5_buf_free(&buf); } int