mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 09:10:53 +02:00
Fix mem_track.h compile failure on multi-threaded non-Linux builds
The memLock mutex and #include <pthread.h> in mem_track.h were
declared under #ifdef DO_MEM_LIST (Linux/macOS/Zephyr only), but
referenced under the broader guard
!defined(SINGLE_THREADED) && \
(defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
Since DO_MEM_STATS is defined whenever WOLFSSL_TRACK_MEMORY +
USE_WOLFSSL_MEMORY are set without WOLFSSL_STATIC_MEMORY, any
non-Linux/Mac/Zephyr multi-threaded build failed to compile with
implicit pthread_mutex_lock declarations and undeclared memLock.
Replace the raw pthread mutex with wolfSSL's portable mutex API
(wc_InitMutex / wc_LockMutex / wc_UnLockMutex / wc_FreeMutex) so
locking works on every platform wolfSSL already ports to.
InitMemoryTracker now calls wc_InitMutex before
wolfSSL_SetAllocators installs TrackMalloc, guarded by a
memLockInit flag for idempotency. CleanupMemoryTracker calls
wc_FreeMutex after restoring the default allocators so no
in-flight allocation races a freed mutex. The four mutex guards
in TrackMalloc/TrackFree and the two in InitMemoryTracker/
ShowMemoryTracker are unified on the same condition as the
memLock declaration itself.
ZD #21763
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
name: FreeRTOS mem_track.h compile regression
|
||||
|
||||
# START OF COMMON SECTION
|
||||
on:
|
||||
push:
|
||||
branches: [ 'master', 'main', 'release/**' ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
# END OF COMMON SECTION
|
||||
|
||||
# Regression test for the memLock / pthread.h guard misalignment in
|
||||
# wolfssl/wolfcrypt/mem_track.h that previously broke multi-threaded
|
||||
# FreeRTOS-class builds with WOLFSSL_TRACK_MEMORY + USE_WOLFSSL_MEMORY
|
||||
# + !WOLFSSL_STATIC_MEMORY. The bug was preprocessor-only, so the test
|
||||
# simulates a non-Linux/Mac/Zephyr target by suppressing the host
|
||||
# platform autodefines (-U__linux__ -U__MACH__ -U__ZEPHYR__) and using
|
||||
# the clean-room FreeRTOS.h / semphr.h stubs under
|
||||
# tests/freertos-mem-track-repro/. No cross compiler needed.
|
||||
|
||||
jobs:
|
||||
freertos_mem_track:
|
||||
name: mem_track.h non-Linux multi-threaded compile
|
||||
if: github.repository_owner == 'wolfssl'
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout wolfSSL
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run mem_track.h FreeRTOS reproducer
|
||||
run: sh tests/freertos-mem-track-repro/run.sh
|
||||
@@ -0,0 +1,38 @@
|
||||
/* FreeRTOS.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Stub FreeRTOS.h for the mem_track.h reproducer.
|
||||
*
|
||||
* Provides the minimum typedefs the wolfSSL header chain needs while
|
||||
* pretending to be a non-Linux multi-threaded FreeRTOS target. */
|
||||
#ifndef WOLFSSL_REPRO_FREERTOS_H
|
||||
#define WOLFSSL_REPRO_FREERTOS_H
|
||||
|
||||
typedef void *SemaphoreHandle_t;
|
||||
typedef void *xSemaphoreHandle;
|
||||
typedef void *TaskHandle_t;
|
||||
|
||||
/* mem_track.h calls these directly under #ifdef FREERTOS. Declarations
|
||||
* only; the test compiles -c and never links. */
|
||||
extern void *pvPortMalloc(unsigned long size);
|
||||
extern void vPortFree(void *ptr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/* repro.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Reproduces the memLock / pthread.h compile failure reported by the
|
||||
* FreeRTOS/Xtensa customer in wolfSSL 5.9.1. The bug is preprocessor-only
|
||||
* so it triggers on any host once __linux__/__MACH__/__ZEPHYR__ are
|
||||
* suppressed via -U flags. WOLFSSL_USER_SETTINGS is supplied by run.sh. */
|
||||
#include "user_settings.h"
|
||||
#include "wolfssl/wolfcrypt/settings.h"
|
||||
#include "wolfssl/wolfcrypt/mem_track.h"
|
||||
|
||||
int main(void) { return 0; }
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
# run.sh
|
||||
#
|
||||
# Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
#
|
||||
# This file is part of wolfSSL.
|
||||
#
|
||||
# wolfSSL is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# wolfSSL is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
|
||||
# Regression test for the mem_track.h memLock guard misalignment that
|
||||
# previously broke multi-threaded FreeRTOS-class builds with
|
||||
# WOLFSSL_TRACK_MEMORY + USE_WOLFSSL_MEMORY + !WOLFSSL_STATIC_MEMORY.
|
||||
#
|
||||
# The bug is preprocessor-only, so the test runs on a stock Linux host:
|
||||
# -U__linux__ -U__MACH__ -U__ZEPHYR__ suppresses the host autodefines
|
||||
# that would otherwise hide it. Stub FreeRTOS.h / semphr.h satisfy the
|
||||
# wc_port.h FREERTOS_TCP mutex typedef without needing a real RTOS.
|
||||
#
|
||||
# Exit 0 = mem_track.h still compiles in the non-Linux multi-threaded
|
||||
# config, i.e. the fix is in place. Exit non-zero = the misalignment is
|
||||
# back. Run from the wolfssl repo root.
|
||||
set -u
|
||||
cc -DWOLFSSL_USER_SETTINGS \
|
||||
-U__linux__ -U__MACH__ -U__ZEPHYR__ \
|
||||
-I tests/freertos-mem-track-repro \
|
||||
-I . \
|
||||
-c tests/freertos-mem-track-repro/repro.c \
|
||||
-o /dev/null
|
||||
status=$?
|
||||
if [ $status -eq 0 ]; then
|
||||
echo "OK: mem_track.h compiles for non-Linux multi-threaded config."
|
||||
else
|
||||
echo "FAIL: mem_track.h compile broken for non-Linux multi-threaded" >&2
|
||||
echo " config - the memLock guard misalignment may be back." >&2
|
||||
fi
|
||||
exit $status
|
||||
@@ -0,0 +1,26 @@
|
||||
/* semphr.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Stub semphr.h for the mem_track.h reproducer. SemaphoreHandle_t is
|
||||
* declared in the stub FreeRTOS.h. */
|
||||
#ifndef WOLFSSL_REPRO_SEMPHR_H
|
||||
#define WOLFSSL_REPRO_SEMPHR_H
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/* task.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Stub task.h for the mem_track.h reproducer. The wolfSSL header chain
|
||||
* includes this when FREERTOS is defined; we don't need any of the real
|
||||
* task API to reach the mem_track.h code under test. */
|
||||
#ifndef WOLFSSL_REPRO_TASK_H
|
||||
#define WOLFSSL_REPRO_TASK_H
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/* user_settings.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Minimal user_settings.h reproducing the bug state. */
|
||||
#ifndef WOLFSSL_FREERTOS_MEM_TRACK_REPRO_USER_SETTINGS_H
|
||||
#define WOLFSSL_FREERTOS_MEM_TRACK_REPRO_USER_SETTINGS_H
|
||||
|
||||
#define FREERTOS
|
||||
#define FREERTOS_TCP
|
||||
#define NO_FILESYSTEM
|
||||
#define WOLFSSL_NO_SOCK
|
||||
#define USE_WOLFSSL_MEMORY
|
||||
#define WOLFSSL_TRACK_MEMORY
|
||||
#define WOLFSSL_DEBUG_MEMORY
|
||||
#define WOLFSSL_DEBUG_MEMORY_PRINT
|
||||
#define DEBUG_WOLFSSL
|
||||
|
||||
/* Intentionally NOT defined: SINGLE_THREADED, WOLFSSL_STATIC_MEMORY */
|
||||
|
||||
#endif
|
||||
+7
-1
@@ -88,5 +88,11 @@ EXTRA_DIST += tests/unit.h \
|
||||
tests/emnet/IP/IP.h \
|
||||
tests/emnet/emnet_shim.c \
|
||||
tests/emnet/emnet_nonblock_test.c \
|
||||
tests/emnet/Makefile
|
||||
tests/emnet/Makefile \
|
||||
tests/freertos-mem-track-repro/user_settings.h \
|
||||
tests/freertos-mem-track-repro/repro.c \
|
||||
tests/freertos-mem-track-repro/FreeRTOS.h \
|
||||
tests/freertos-mem-track-repro/semphr.h \
|
||||
tests/freertos-mem-track-repro/task.h \
|
||||
tests/freertos-mem-track-repro/run.sh
|
||||
DISTCLEANFILES+= tests/.libs/unit.test
|
||||
|
||||
@@ -142,9 +142,12 @@ static memoryStats ourMemStats;
|
||||
WOLFSSL_API extern memoryStats *wc_MemStats_Ptr;
|
||||
|
||||
#ifdef DO_MEM_LIST
|
||||
#include <pthread.h>
|
||||
static memoryList ourMemList;
|
||||
static pthread_mutex_t memLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
static wolfSSL_Mutex memLock;
|
||||
static int memLockInit = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DEBUG_MEMORY
|
||||
@@ -182,7 +185,7 @@ static WC_INLINE void* TrackMalloc(size_t sz)
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
if (pthread_mutex_lock(&memLock) == 0)
|
||||
if (wc_LockMutex(&memLock) == 0)
|
||||
{
|
||||
#endif
|
||||
|
||||
@@ -228,9 +231,9 @@ static WC_INLINE void* TrackMalloc(size_t sz)
|
||||
ourMemList.count++;
|
||||
#endif
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
pthread_mutex_unlock(&memLock);
|
||||
wc_UnLockMutex(&memLock);
|
||||
}
|
||||
#endif /* DO_MEM_LIST */
|
||||
#endif /* !SINGLE_THREADED && (DO_MEM_LIST || DO_MEM_STATS) */
|
||||
|
||||
return header->thisMemory;
|
||||
}
|
||||
@@ -255,7 +258,7 @@ static WC_INLINE void TrackFree(void* ptr)
|
||||
sz = header->thisSize;
|
||||
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
if (pthread_mutex_lock(&memLock) == 0)
|
||||
if (wc_LockMutex(&memLock) == 0)
|
||||
{
|
||||
#endif
|
||||
|
||||
@@ -289,7 +292,7 @@ static WC_INLINE void TrackFree(void* ptr)
|
||||
#endif
|
||||
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
pthread_mutex_unlock(&memLock);
|
||||
wc_UnLockMutex(&memLock);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -362,14 +365,27 @@ static WC_INLINE int InitMemoryTracker(void)
|
||||
if (ret < 0) {
|
||||
wc_mem_printf("wolfSSL GetAllocators failed to get the defaults\n");
|
||||
}
|
||||
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
/* Init the mutex before installing the tracking allocators, so the
|
||||
* mutex is ready as soon as another thread can enter TrackMalloc. */
|
||||
if (!memLockInit) {
|
||||
if (wc_InitMutex(&memLock) != 0) {
|
||||
wc_mem_printf("wc_InitMutex failed for track memory\n");
|
||||
return -1;
|
||||
}
|
||||
memLockInit = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc);
|
||||
if (ret < 0) {
|
||||
wc_mem_printf("wolfSSL SetAllocators failed for track memory\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DO_MEM_LIST
|
||||
if (pthread_mutex_lock(&memLock) == 0)
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
if (wc_LockMutex(&memLock) == 0)
|
||||
#endif
|
||||
{
|
||||
#ifdef DO_MEM_STATS
|
||||
@@ -387,8 +403,11 @@ static WC_INLINE int InitMemoryTracker(void)
|
||||
#ifdef DO_MEM_LIST
|
||||
XMEMSET(&ourMemList, 0, sizeof(ourMemList));
|
||||
ourMemStats.memList = &ourMemList;
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock(&memLock);
|
||||
#if !defined(SINGLE_THREADED) && \
|
||||
(defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
wc_UnLockMutex(&memLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -399,8 +418,8 @@ static WC_INLINE int InitMemoryTracker(void)
|
||||
|
||||
static WC_INLINE void ShowMemoryTracker(void)
|
||||
{
|
||||
#ifdef DO_MEM_LIST
|
||||
if (pthread_mutex_lock(&memLock) == 0)
|
||||
#if !defined(SINGLE_THREADED) && (defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
if (wc_LockMutex(&memLock) == 0)
|
||||
#endif
|
||||
{
|
||||
#ifdef DO_MEM_STATS
|
||||
@@ -429,8 +448,11 @@ static WC_INLINE void ShowMemoryTracker(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock(&memLock);
|
||||
#if !defined(SINGLE_THREADED) && \
|
||||
(defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
|
||||
wc_UnLockMutex(&memLock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -438,7 +460,13 @@ static WC_INLINE void ShowMemoryTracker(void)
|
||||
static WC_INLINE int CleanupMemoryTracker(void)
|
||||
{
|
||||
wc_MemStats_Ptr = NULL;
|
||||
/* restore default allocators */
|
||||
/* Restore default allocators. memLock is intentionally left
|
||||
* initialized for process lifetime (matching the prior static
|
||||
* PTHREAD_MUTEX_INITIALIZER behavior): SetAllocators stops new
|
||||
* entries into TrackMalloc/TrackFree but does not synchronize
|
||||
* with in-flight calls, so freeing the mutex here would be a
|
||||
* use-after-free hazard. The memLockInit flag keeps re-Init
|
||||
* idempotent across an Init/Cleanup/Init cycle. */
|
||||
return wolfSSL_SetAllocators(mfDefault, ffDefault, rfDefault);
|
||||
}
|
||||
#endif /* WOLFSSL_TRACK_MEMORY && USE_WOLFSSL_MEMORY && \
|
||||
|
||||
Reference in New Issue
Block a user