Skip to content

Commit

Permalink
Merge pull request katef#493 from katef/sv/bugfix-endid-qsort-count
Browse files Browse the repository at this point in the history
bugfix: fsm_endid_get should sort with result count, not buffer size.
  • Loading branch information
katef authored Sep 13, 2024
2 parents 81b14f8 + dec6ec0 commit 521789f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/libfsm/endids.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ fsm_endid_get(const struct fsm *fsm, fsm_state_t end_state,
{
size_t i;
const struct endid_info *ei = NULL;
size_t result_count = 0;

uint64_t hash = hash_id(end_state);
uint64_t mask;
Expand Down Expand Up @@ -735,9 +736,10 @@ fsm_endid_get(const struct fsm *fsm, fsm_state_t end_state,
#endif
ids[id_i] = b->ids->ids[id_i];
}
result_count = b->ids->count;

/* sorting for caller convenience */
qsort(ids, count, sizeof *ids, cmp_endids);
qsort(ids, result_count, sizeof *ids, cmp_endids);

return 1;
} else { /* collision */
Expand Down
57 changes: 57 additions & 0 deletions tests/endids/endids_reused_buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <errno.h>

#include <assert.h>

#include <re/re.h>

#include <fsm/fsm.h>
#include <fsm/bool.h>
#include <fsm/pred.h>
#include <fsm/print.h>
#include <fsm/walk.h>

#include "endids_utils.h"

/* Test that providing an overly large endid buffer doesn't clobber the result with stale data. */
int main(void)
{
const char *input = "banana turtle";

const char *s = input;
struct fsm *fsm = re_comp(RE_NATIVE, fsm_sgetc, &s, NULL, 0, NULL);
int ret;

ret = fsm_setendid(fsm, (fsm_end_id_t) 12345);
assert(ret == 1);

ret = fsm_determinise(fsm);
assert(ret == 1);

ret = fsm_minimise(fsm);
assert(ret == 1);

fsm_state_t end;
ret = fsm_exec(fsm, fsm_sgetc, &input, &end, NULL);
assert(ret == 1);

const size_t endid_count = fsm_endid_count(fsm, end);
assert(endid_count == 1);

/* Regression: fsm_endid_get previously qsort'd endids with
* a count based on the buffer size (here ENDID_BUF_CEIL),
* rather than the number of results populated, so if the
* buffer was larger than fsm_endid_count's result stale
* contents could displace the correct results. */
#define ENDID_BUF_CEIL 10
fsm_end_id_t endids[ENDID_BUF_CEIL] = { 333 };
ret = fsm_endid_get(fsm, end, ENDID_BUF_CEIL, endids);
assert(endids[0] == 12345);

fsm_free(fsm);
return EXIT_SUCCESS;
}

0 comments on commit 521789f

Please sign in to comment.