Skip to content

Commit

Permalink
add wolfsentry_lock_shared2mutex_is_reserved() and use it to mitigate…
Browse files Browse the repository at this point in the history
… a test harness race in test_rw_locks();

fix file handle leak in unittests.c:json_feed_file(();

fix unchecked fd in unittests.c:test_json_corpus() reported by clang-analyzer-unix.StdCLibraryFunctions;

coddle analyzer: clang-analyzer-unix.Stream and readability-math-missing-parentheses from clang-tidy-19-pre20240509;

fix doxygen documentation for wolfsentry_lock_have_shared2mutex_reservation();

rebuild doc/wolfSentry_refman.pdf.
  • Loading branch information
douzzer committed May 17, 2024
1 parent 857c85d commit 7cdf15e
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 15 deletions.
Binary file modified doc/wolfSentry_refman.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion src/json/centijson_sax.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ json_string_automaton(JSON_PARSER* parser, const unsigned char* input, size_t si
/* parser->codepoint[0] & [1] form valid surrogate pair. */
uint32_t hi = parser->codepoint[0];
uint32_t lo = parser->codepoint[1];
uint32_t codepoint = 0x10000 + (hi - 0xd800) * 0x400 + (lo - 0xdc00);
uint32_t codepoint = 0x10000 + ((hi - 0xd800) * 0x400) + (lo - 0xdc00);
if(json_buf_append_codepoint(parser, codepoint) < 0)
break;
parser->substate = 0;
Expand Down
10 changes: 10 additions & 0 deletions src/wolfsentry_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -3025,6 +3025,16 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_have_shared2mutex_reservatio
WOLFSENTRY_ERROR_RETURN(NOT_OK);
}

WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_is_reserved(struct wolfsentry_rwlock *lock, struct wolfsentry_thread_context *thread, wolfsentry_lock_flags_t flags) {
(void)flags;
WOLFSENTRY_LOCK_ASSERT_INITED(lock);
WOLFSENTRY_THREAD_ASSERT_INITED(thread);
if (WOLFSENTRY_ATOMIC_LOAD(lock->read2write_reservation_holder) == WOLFSENTRY_THREAD_NO_ID)
WOLFSENTRY_SUCCESS_RETURN(NO);
else
WOLFSENTRY_SUCCESS_RETURN(YES);
}

WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_get_flags(struct wolfsentry_rwlock *lock, struct wolfsentry_thread_context *thread, wolfsentry_lock_flags_t *flags) {
(void)thread;
WOLFSENTRY_LOCK_ASSERT_INITED(lock);
Expand Down
34 changes: 22 additions & 12 deletions tests/unittests.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,25 +453,25 @@ static __attribute_maybe_unused__ wolfsentry_errcode_t load_test_action_handlers
static __attribute_maybe_unused__ wolfsentry_errcode_t json_feed_file(WOLFSENTRY_CONTEXT_ARGS_IN, const char *fname, wolfsentry_config_load_flags_t flags, int verbose) {
wolfsentry_errcode_t ret;
struct wolfsentry_json_process_state *jps;
FILE *f;
FILE *f = NULL;
unsigned char buf[512];
char err_buf[512];
int fini_ret;

if (strcmp(fname,"-"))
if (strcmp(fname,"-")) {
f = fopen(fname, "r");
else
f = stdin;
if (! f) {
fprintf(stderr, "fopen(%s): %s\n",fname,strerror(errno));
WOLFSENTRY_ERROR_RETURN(UNIT_TEST_FAILURE);
if (! f) {
fprintf(stderr, "fopen(%s): %s\n",fname,strerror(errno));
WOLFSENTRY_ERROR_RETURN(UNIT_TEST_FAILURE);
}
}

ret = wolfsentry_config_json_init(WOLFSENTRY_CONTEXT_ARGS_OUT, flags, &jps);
WOLFSENTRY_RERETURN_IF_ERROR(ret);
if (ret < 0)
goto out;

for (;;) {
size_t n = fread(buf, 1, sizeof buf, f);
size_t n = fread(buf, 1, sizeof buf, f ? f : stdin);
if ((n < sizeof buf) && ferror(f)) {
fprintf(stderr,"fread(%s): %s\n",fname, strerror(errno));
ret = WOLFSENTRY_ERROR_ENCODE(UNIT_TEST_FAILURE);
Expand Down Expand Up @@ -500,7 +500,7 @@ static __attribute_maybe_unused__ wolfsentry_errcode_t json_feed_file(WOLFSENTRY
if (WOLFSENTRY_ERROR_CODE_IS(ret, OK))
ret = WOLFSENTRY_ERROR_ENCODE(OK);

if (f != stdin)
if (f)
fclose(f);

if ((ret < 0) && verbose)
Expand Down Expand Up @@ -1167,6 +1167,9 @@ usleep(10000);

WAIT_FOR_PHASE(thread3_args, 1);

while (WOLFSENTRY_SUCCESS_CODE_IS(wolfsentry_lock_shared2mutex_is_reserved(lock, thread, 0), NO))
usleep(10000);

/* this one must fail, because at this point thread2 must be in shared2mutex wait. */
WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(BUSY, wolfsentry_lock_shared2mutex(lock, thread, WOLFSENTRY_LOCK_FLAG_NONE));

Expand Down Expand Up @@ -1630,7 +1633,7 @@ static int test_static_routes(void) {
{
byte *i;
const byte *i_end;
for (i = private_data, i_end = private_data + private_data_size; i < i_end; ++i)
for (i = private_data, i_end = (private_data + private_data_size); i < i_end; ++i)
*i = 'x';
}

Expand Down Expand Up @@ -4921,6 +4924,7 @@ static int test_json_corpus(void) {
JSON_VALUE p_root, p_clone;
JSON_INPUT_POS json_pos;
DIR *corpus_dir;
int corpus_dirfd;
struct dirent *scenario_ent;
int scenario_fd;
struct stat st;
Expand Down Expand Up @@ -5004,6 +5008,12 @@ static int test_json_corpus(void) {
ret = WOLFSENTRY_ERROR_ENCODE(SYS_OP_FATAL);
break;
}
corpus_dirfd = dirfd(corpus_dir);
if (corpus_dirfd < 0) {
perror(corpus_path);
ret = WOLFSENTRY_ERROR_ENCODE(SYS_OP_FATAL);
break;
}

json_value_init_null(&p_root);
json_value_init_null(&p_clone);
Expand All @@ -5014,7 +5024,7 @@ static int test_json_corpus(void) {
continue;
if (strcmp(scenario_ent->d_name + strlen(scenario_ent->d_name) - strlen(".json"), ".json") != 0)
continue;
scenario_fd = openat(dirfd(corpus_dir), scenario_ent->d_name, O_RDONLY);
scenario_fd = openat(corpus_dirfd, scenario_ent->d_name, O_RDONLY);
if (scenario_fd < 0) {
perror(scenario_ent->d_name);
continue;
Expand Down
18 changes: 16 additions & 2 deletions wolfsentry/wolfsentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -678,12 +678,26 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_have_either(struct wolfsentr
\param thread pointer to the `wolfsentry_thread_context`
\param flags optional `wolfsentry_lock_flags_t`
\return When decoded using WOLFSENTRY_ERROR_DECODE_ERROR_CODE(), WOLFSENTRY_ERROR_ID_OK if
it is shared lock. Or WOLFSENTRY_ERROR_ID_NOT_OK if it is not a shared lock.
\return When decoded using WOLFSENTRY_ERROR_DECODE_ERROR_CODE(),
WOLFSENTRY_ERROR_ID_OK if the supplied thread has a reservation on the lock. Or
WOLFSENTRY_ERROR_ID_NOT_OK if no reservation is held.
\sa WOLFSENTRY_ERROR_DECODE_ERROR_CODE
*/
WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_have_shared2mutex_reservation(struct wolfsentry_rwlock *lock, struct wolfsentry_thread_context *thread, wolfsentry_lock_flags_t flags);
/*!
\brief Check if any thread holds an upgrade reservation on the lock
\param lock a pointer to the lock
\param thread pointer to the `wolfsentry_thread_context`
\param flags optional `wolfsentry_lock_flags_t`
\return When decoded using WOLFSENTRY_ERROR_DECODE_ERROR_CODE(), WOLFSENTRY_SUCCESS_ID_YES if
a reservation is held by some thread, or WOLFSENTRY_SUCCESS_ID_NO if not.
\sa WOLFSENTRY_ERROR_DECODE_ERROR_CODE
*/
WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_is_reserved(struct wolfsentry_rwlock *lock, struct wolfsentry_thread_context *thread, wolfsentry_lock_flags_t flags);
/*!
\brief Extract the current flags from the lock
Expand Down

0 comments on commit 7cdf15e

Please sign in to comment.