fix: correction bugs + tests + migration el7 vers el10

Correctifs de bugs critiques:
- Overflow entier dans le calcul du timestamp (nanoseconds)
- Validation des composantes temporelles dans format_iso8601
- Race condition mutex: échec dur pour MPM threadés (worker/event)
- Rejet des espaces en tête dans parse_int_strict

Nouveaux tests unitaires (38 ajoutés):
- Overflow timestamp, limites ISO8601, format fixe 20 chars
- Limite de taille JSON 64KB
- Détection headers sensibles (blacklist)
- Validation parse_int_strict
- dynbuf NULL handling et strlen mode

Migration packaging:
- Suppression CentOS 7 (EOL)
- Ajout AlmaLinux 10 (el10)
- RPMs supportés: el8, el9, el10

Mise à jour CI/CD et documentation:
- .gitlab-ci.yml: jobs verify pour el8/el9/el10
- architecture.yml: OS supportés à jour
- 70/70 tests pass

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Jacquin Antoine
2026-02-28 21:02:05 +01:00
parent 59856a7ed7
commit d0ca0a7e4c
8 changed files with 624 additions and 117 deletions

View File

@ -15,6 +15,7 @@
#include "apr_time.h"
#include "apr_lib.h"
#include "ap_config.h"
#include "ap_mpm.h"
#include <sys/socket.h>
#include <sys/un.h>
@ -237,10 +238,33 @@ static void format_iso8601(dynbuf_t *db, apr_time_t t)
apr_time_exp_t tm;
apr_time_exp_gmt(&tm, t);
/* Validate time components to prevent buffer overflow and invalid output.
* apr_time_exp_gmt should always produce valid values, but we validate
* defensively to catch any APR bugs or memory corruption. */
int year = tm.tm_year + 1900;
int mon = tm.tm_mon + 1;
int day = tm.tm_mday;
int hour = tm.tm_hour;
int min = tm.tm_min;
int sec = tm.tm_sec;
/* Clamp values to valid ranges to ensure fixed-width output (20 chars + null) */
if (year < 0) year = 0;
if (year > 9999) year = 9999;
if (mon < 1) mon = 1;
if (mon > 12) mon = 12;
if (day < 1) day = 1;
if (day > 31) day = 31;
if (hour < 0) hour = 0;
if (hour > 23) hour = 23;
if (min < 0) min = 0;
if (min > 59) min = 59;
if (sec < 0) sec = 0;
if (sec > 61) sec = 61;
char time_str[32];
snprintf(time_str, sizeof(time_str), "%04d-%02d-%02dT%02d:%02d:%02dZ",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
year, mon, day, hour, min, sec);
dynbuf_append(db, time_str, -1);
}
@ -249,6 +273,10 @@ static int parse_int_strict(const char *arg, int *out)
char *end = NULL;
long v;
if (arg == NULL || *arg == '\0' || out == NULL) return -1;
/* Reject leading whitespace (strtol skips it by default) */
if (apr_isspace(*arg)) return -1;
errno = 0;
v = strtol(arg, &end, 10);
if (errno != 0 || end == arg || *end != '\0' || v < INT_MIN || v > INT_MAX) return -1;
@ -644,7 +672,8 @@ static void log_request(request_rec *r, reqin_log_config_t *cfg, reqin_log_child
/* timestamp (nanoseconds since epoch) */
{
apr_time_t now = apr_time_now();
apr_uint64_t ns = (apr_uint64_t)now * 1000;
/* Cast to apr_uint64_t before multiplication to prevent overflow */
apr_uint64_t ns = ((apr_uint64_t)now) * APR_UINT64_C(1000);
char ts_buf[32];
snprintf(ts_buf, sizeof(ts_buf), "%" APR_UINT64_T_FMT, ns);
dynbuf_append(&buf, "\"timestamp\":", 12);
@ -799,6 +828,8 @@ static int reqin_log_post_read_request(request_rec *r)
static void reqin_log_child_init(apr_pool_t *p, server_rec *s)
{
reqin_log_server_conf_t *srv_conf = get_server_conf(s);
int threaded_mpm = 0;
int mpm_threads;
if (srv_conf == NULL) {
return;
@ -809,12 +840,31 @@ static void reqin_log_child_init(apr_pool_t *p, server_rec *s)
srv_conf->child_state.last_error_report = 0;
srv_conf->child_state.connect_failed = 0;
/* Detect if we're running in a threaded MPM (worker/event) */
if (ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_threads) == APR_SUCCESS &&
mpm_threads > 0) {
threaded_mpm = 1;
}
srv_conf->child_state.fd_mutex = NULL;
if (apr_thread_mutex_create(&srv_conf->child_state.fd_mutex,
APR_THREAD_MUTEX_DEFAULT, p) != APR_SUCCESS) {
srv_conf->child_state.fd_mutex = NULL;
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
MOD_REQIN_LOG_NAME ": Failed to create mutex, continuing in degraded mode");
if (threaded_mpm) {
/* Critical error: cannot ensure thread safety in worker/event MPM */
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
MOD_REQIN_LOG_NAME ": Failed to create mutex for thread safety. "
"Module cannot operate safely in threaded MPM. Disabling.");
/* Disable module by clearing config */
srv_conf->config->enabled = 0;
return;
} else {
/* Prefork MPM: single thread per process, mutex not strictly needed */
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
MOD_REQIN_LOG_NAME ": Failed to create mutex, continuing in "
"degraded mode (prefork MPM detected)");
}
}
if (srv_conf->config == NULL || !srv_conf->config->enabled ||