v0.1.12 - Fix if-else chain bug preventing SELECTOR_ROLE_PATH derivation; fix parser to not treat 44' as variable; handle hardened markers on range/set segments

This commit is contained in:
Laan Tungir
2026-08-04 21:21:33 -04:00
parent f0e90e0ea6
commit d7fb3787e6
2 changed files with 34 additions and 10 deletions
+28 -9
View File
@@ -800,8 +800,8 @@ int socket_name_random(char *out, size_t out_len);
/* Version information (auto-updated by build/version tooling) */
#define NSIGNER_VERSION_MAJOR 0
#define NSIGNER_VERSION_MINOR 1
#define NSIGNER_VERSION_PATCH 11
#define NSIGNER_VERSION "v0.1.11"
#define NSIGNER_VERSION_PATCH 12
#define NSIGNER_VERSION "v0.1.12"
/* NSIGNER_HEADERLESS_DECLS_END */
@@ -2063,8 +2063,21 @@ static int parse_path_template_for_role(const char *token,
seg[seg_len] = '\0';
if (!found_range) {
/* Check for range/set markers first. Only strip hardened marker
* (' or h) from segments that contain - or + (range/set forms).
* A plain number with ' (like 44') is a literal hardened constant,
* NOT a variable. */
char *plus = strchr(seg, '+');
char *dash = strchr(seg, '-');
int is_range_or_set = (plus != NULL || dash != NULL);
int seg_hardened = 0;
if (is_range_or_set && seg_len > 0 &&
(seg[seg_len - 1] == '\'' || seg[seg_len - 1] == 'h' || seg[seg_len - 1] == 'H')) {
seg_hardened = 1;
seg[seg_len - 1] = '\0';
seg_len--;
}
if (plus != NULL) {
/* Set form: "1+34+54" or "1+3-5+10" */
@@ -2104,11 +2117,12 @@ static int parse_path_template_for_role(const char *token,
*allowed_count_out = set_count;
*range_lo = allowed_indices_out[0];
*range_hi = allowed_indices_out[set_count - 1];
if (strlen(template_out) + 3 >= template_sz) return -1;
if (strlen(template_out) + 5 >= template_sz) return -1;
strcat(template_out, "%d");
if (seg_hardened) strcat(template_out, "'");
strcat(template_out, "/");
} else {
if (strlen(template_out) + seg_len + 2 >= template_sz) return -1;
if (strlen(template_out) + seg_len + 3 >= template_sz) return -1;
strcat(template_out, seg);
strcat(template_out, "/");
}
@@ -2119,30 +2133,35 @@ static int parse_path_template_for_role(const char *token,
long lo = strtol(seg, &e1, 10);
long hi = strtol(dash + 1, &e2, 10);
if (*e1 != '\0' || *e2 != '\0' || lo < 0 || hi < 0 || lo > hi) {
if (strlen(template_out) + seg_len + 2 >= template_sz) return -1;
*dash = '-'; /* restore dash */
if (strlen(template_out) + seg_len + 3 >= template_sz) return -1;
strcat(template_out, seg);
strcat(template_out, "/");
} else {
found_range = 1;
*range_lo = (int)lo;
*range_hi = (int)hi;
if (strlen(template_out) + 3 >= template_sz) return -1;
if (strlen(template_out) + 5 >= template_sz) return -1;
strcat(template_out, "%d");
if (seg_hardened) strcat(template_out, "'");
strcat(template_out, "/");
}
} else {
/* Single number */
/* Single number — only treat as variable if NO hardened marker.
* A segment like "44'" is a literal hardened constant. */
char *e = NULL;
long v = strtol(seg, &e, 10);
if (*e != '\0' || v < 0) {
if (strlen(template_out) + seg_len + 2 >= template_sz) return -1;
/* Not a plain number (has ' or other chars) — literal */
if (strlen(template_out) + seg_len + 3 >= template_sz) return -1;
strcat(template_out, seg);
strcat(template_out, "/");
} else {
/* Plain number without ' — this is the variable */
found_range = 1;
*range_lo = (int)v;
*range_hi = (int)v;
if (strlen(template_out) + 3 >= template_sz) return -1;
if (strlen(template_out) + 5 >= template_sz) return -1;
strcat(template_out, "%d");
strcat(template_out, "/");
}
+6 -1
View File
@@ -2374,7 +2374,8 @@ int server_handle_one(server_ctx_t *ctx, server_activity_cb cb, void *cb_data) {
if (extract_method_and_selector(request, method, sizeof(method), &selector_req) == 0) {
if (ctx->dispatcher->role_table != NULL) {
selector_rc = selector_resolve(&selector_req, ctx->dispatcher->role_table, &role);
if (selector_rc == SELECTOR_OK && role != NULL) {
if (selector_rc == SELECTOR_OK && role != NULL &&
role->selector_type == SELECTOR_NOSTR_INDEX) {
json_copy_string(role_name, sizeof(role_name), role->name, "main");
json_copy_string(purpose, sizeof(purpose), role_purpose_to_str(role->purpose), "nostr");
} else if (selector_rc == SELECTOR_ERR_NOT_FOUND && selector_req.has_nostr_index) {
@@ -2398,6 +2399,8 @@ int server_handle_one(server_ctx_t *ctx, server_activity_cb cb, void *cb_data) {
role->selector_type == SELECTOR_ROLE_PATH &&
strstr(role->role_path, "%d") == NULL) {
/* Fixed-path named role — no index needed, derive if not yet done */
json_copy_string(role_name, sizeof(role_name), role->name, "main");
json_copy_string(purpose, sizeof(purpose), role_purpose_to_str(role->purpose), "nostr");
if (!role->derived) {
pending_derivation = 1;
}
@@ -2405,6 +2408,8 @@ int server_handle_one(server_ctx_t *ctx, server_activity_cb cb, void *cb_data) {
role->selector_type == SELECTOR_ROLE_PATH &&
strstr(role->role_path, "%d") != NULL) {
/* Named path-role with template — resolve the concrete path from index */
json_copy_string(role_name, sizeof(role_name), role->name, "main");
json_copy_string(purpose, sizeof(purpose), role_purpose_to_str(role->purpose), "nostr");
int chosen_index;
if (selector_req.has_index) {
chosen_index = selector_req.index;