ci: drop sanitizers job; harden test_subagent fake server
test_subagent segfaulted in the Docker runner: the fake SSE handler took user + strlen(user) - 1 with an empty user string. Guard JSON access and format the child report with an empty-safe last character. Remove the sanitizers job entirely (if: false still queued it and blocked the runner).
This commit is contained in:
@@ -49,37 +49,6 @@ jobs:
|
|||||||
./cst-agent --workspace "$PWD" --list-sessions
|
./cst-agent --workspace "$PWD" --list-sessions
|
||||||
./cst-agent --demo-ctl --workspace .
|
./cst-agent --demo-ctl --workspace .
|
||||||
|
|
||||||
# Disabled: Docker runner lacks SYS_PTRACE; ASan spins on DEADLYSIGNAL and
|
|
||||||
# wedged the only runner. Re-enable after the runner gets --cap-add SYS_PTRACE
|
|
||||||
# (or seccomp=unconfined).
|
|
||||||
sanitizers:
|
|
||||||
if: false
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 15
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
env:
|
|
||||||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
|
||||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
||||||
GITHUB_SHA: ${{ github.sha }}
|
|
||||||
run: |
|
|
||||||
curl -fsSL "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/raw/commit/$GITHUB_SHA/scripts/ci_checkout.sh" \
|
|
||||||
-o /tmp/ci_checkout.sh
|
|
||||||
bash /tmp/ci_checkout.sh
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
SUDO=$(command -v sudo || true)
|
|
||||||
$SUDO bash scripts/ci_pkg_mirror.sh
|
|
||||||
$SUDO apt-get update
|
|
||||||
$SUDO apt-get install -y --no-install-recommends \
|
|
||||||
build-essential pkg-config libcurl4-openssl-dev libncurses-dev
|
|
||||||
- name: ASan + UBSan
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
ASAN_OPTIONS: abort_on_error=1:halt_on_error=1:detect_leaks=0:use_sigaltstack=0
|
|
||||||
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
|
|
||||||
run: timeout -s KILL 480 make asan
|
|
||||||
|
|
||||||
musl:
|
musl:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
|||||||
+23
-10
@@ -93,7 +93,7 @@ static void reply_calls(test_sock_t fd, const char *const *calls, int n) {
|
|||||||
cJSON *tc = cJSON_AddArrayToObject(d, "tool_calls");
|
cJSON *tc = cJSON_AddArrayToObject(d, "tool_calls");
|
||||||
cJSON *c = cJSON_CreateObject();
|
cJSON *c = cJSON_CreateObject();
|
||||||
cJSON_AddNumberToObject(c, "index", i);
|
cJSON_AddNumberToObject(c, "index", i);
|
||||||
char id[16];
|
char id[32];
|
||||||
snprintf(id, sizeof(id), "call_%d", i);
|
snprintf(id, sizeof(id), "call_%d", i);
|
||||||
cJSON_AddStringToObject(c, "id", id);
|
cJSON_AddStringToObject(c, "id", id);
|
||||||
cJSON_AddStringToObject(c, "type", "function");
|
cJSON_AddStringToObject(c, "type", "function");
|
||||||
@@ -120,19 +120,30 @@ static int has_tool(const cJSON *body, const char *name) {
|
|||||||
|
|
||||||
static void handle(test_sock_t fd, const char *body_txt) {
|
static void handle(test_sock_t fd, const char *body_txt) {
|
||||||
cJSON *body = cJSON_Parse(body_txt);
|
cJSON *body = cJSON_Parse(body_txt);
|
||||||
|
if (!body) {
|
||||||
|
const char *err = "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n";
|
||||||
|
send_all(fd, err, strlen(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const cJSON *msgs = cJSON_GetObjectItemCaseSensitive(body, "messages");
|
const cJSON *msgs = cJSON_GetObjectItemCaseSensitive(body, "messages");
|
||||||
int nm = cJSON_GetArraySize(msgs);
|
int nm = cJSON_IsArray(msgs) ? cJSON_GetArraySize(msgs) : 0;
|
||||||
const cJSON *sys = cJSON_GetObjectItemCaseSensitive(
|
const cJSON *sys = NULL;
|
||||||
cJSON_GetArrayItem(msgs, 0), "content");
|
const char *last_role = "";
|
||||||
const cJSON *last = cJSON_GetArrayItem(msgs, nm - 1);
|
|
||||||
const char *last_role =
|
|
||||||
cJSON_GetObjectItemCaseSensitive(last, "role")->valuestring;
|
|
||||||
const char *user = "";
|
const char *user = "";
|
||||||
|
if (nm > 0) {
|
||||||
|
sys = cJSON_GetObjectItemCaseSensitive(cJSON_GetArrayItem(msgs, 0),
|
||||||
|
"content");
|
||||||
|
const cJSON *last = cJSON_GetArrayItem(msgs, nm - 1);
|
||||||
|
const cJSON *lr = cJSON_GetObjectItemCaseSensitive(last, "role");
|
||||||
|
if (cJSON_IsString(lr))
|
||||||
|
last_role = lr->valuestring;
|
||||||
|
}
|
||||||
for (int i = 0; i < nm; i++) {
|
for (int i = 0; i < nm; i++) {
|
||||||
const cJSON *m = cJSON_GetArrayItem(msgs, i);
|
const cJSON *m = cJSON_GetArrayItem(msgs, i);
|
||||||
const cJSON *r = cJSON_GetObjectItemCaseSensitive(m, "role");
|
const cJSON *r = cJSON_GetObjectItemCaseSensitive(m, "role");
|
||||||
const cJSON *c = cJSON_GetObjectItemCaseSensitive(m, "content");
|
const cJSON *c = cJSON_GetObjectItemCaseSensitive(m, "content");
|
||||||
if (strcmp(r->valuestring, "user") == 0 && cJSON_IsString(c))
|
if (cJSON_IsString(r) && strcmp(r->valuestring, "user") == 0 &&
|
||||||
|
cJSON_IsString(c))
|
||||||
user = c->valuestring;
|
user = c->valuestring;
|
||||||
}
|
}
|
||||||
const char *hdr = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\n"
|
const char *hdr = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\n"
|
||||||
@@ -160,8 +171,10 @@ static void handle(test_sock_t fd, const char *body_txt) {
|
|||||||
const char *calls[] = {"read_file", "{\"path\":\"a.txt\"}"};
|
const char *calls[] = {"read_file", "{\"path\":\"a.txt\"}"};
|
||||||
reply_calls(fd, calls, 1);
|
reply_calls(fd, calls, 1);
|
||||||
} else {
|
} else {
|
||||||
char out[256];
|
/* last char of the user prompt (e.g. "Find A" -> "A"); empty-safe */
|
||||||
snprintf(out, sizeof(out), "child report %s", user + strlen(user) - 1);
|
char tag = user[0] ? user[strlen(user) - 1] : '?';
|
||||||
|
char out[64];
|
||||||
|
snprintf(out, sizeof(out), "child report %c", tag);
|
||||||
reply_text(fd, out);
|
reply_text(fd, out);
|
||||||
}
|
}
|
||||||
atomic_fetch_sub(&g_child_active, 1);
|
atomic_fetch_sub(&g_child_active, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user