1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-03-10 10:19:21 +03:00

Compare commits

..

12 Commits

Author SHA1 Message Date
9d27b935b7 Merge pull request #2223 from synqa/fix-memory-leak-loadlanglist
Fix memory leak in LoadLangList()
2026-02-06 15:56:18 +01:00
1e1104d3ba Merge pull request #2221 from synqa/fix-halt-flag
Fix data race on Tick64
2026-02-06 15:55:01 +01:00
074efb5479 Merge pull request #2220 from synqa/fix-thread-counter
Fix race condition in thread counter
2026-02-06 15:54:18 +01:00
fe460de5a6 Fix data race on Tick64
Add lock protection when reading/writing Halt flag to prevent data race.
2026-02-06 21:12:16 +09:00
6ef941db21 Fix memory leak in LoadLangList() 2026-02-06 21:08:52 +09:00
d7d3ec8cac Fix race condition in thread counter
To prevent data races caused by concurrent access from multiple threads,
replace UINT with COUNTER.
2026-02-06 21:03:08 +09:00
68e9f0b593 Merge pull request #2218 from SoftEtherVPN/dependabot/npm_and_yarn/src/bin/hamcore/wwwroot/admin/default/webpack-5.105.0
Build(deps-dev): Bump webpack from 5.94.0 to 5.105.0 in /src/bin/hamcore/wwwroot/admin/default
2026-02-06 07:35:07 +01:00
f1012da5fb Build(deps-dev): Bump webpack in /src/bin/hamcore/wwwroot/admin/default
Bumps [webpack](https://github.com/webpack/webpack) from 5.94.0 to 5.105.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack/compare/v5.94.0...v5.105.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.105.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-05 23:11:11 +00:00
1411d4ceb4 Merge pull request #2217 from synqa/fix-preserve-errno
Fix preserve errno in SIGCHLD signal handler
2026-02-05 15:46:13 +01:00
a3176175f9 Merge pull request #2216 from synqa/fix-ub-leftshift
Fix undefined behavior of left shift
2026-02-05 15:13:46 +01:00
88af7986b4 Fix preserve errno in SIGCHLD signal handler
Signal handler may interrupt code that depends on errno, and waitpid()
may modify errno, therefore, errno must be saved and restored before
returning.
2026-02-05 18:51:58 +09:00
38f102e2e7 Fix undefined behavior of left shift
Left shifting UCHAR promotes it to a signed integer. When the
value is >= 128 and shifted by 24, the result sets the sign bit,
causing undefined behavior. Fixes it by explicit casting to UINT.
2026-02-05 18:48:01 +09:00
9 changed files with 410 additions and 405 deletions

2
.gitignore vendored
View File

@ -210,5 +210,3 @@ developer_tools/stbchecker/**/*.binlog
developer_tools/stbchecker/**/*.nvuser
developer_tools/stbchecker/**/.mfractor/
/vcpkg_installed
_codeql_build_dir/
_codeql_detected_source_root

View File

@ -1190,67 +1190,6 @@ void NnIpSendForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UCHAR ttl, UINT src_i
}
}
// Host IP address cache TTL in milliseconds (60 seconds)
#define HOST_IP_CACHE_TTL_MS 60000
// Check if destination IP is one of the host's own IP addresses
// Uses caching to avoid frequent system calls
// Returns true if dest_ip matches any of the host's IPs
bool IsDestinationHostOwnIP(VH *v, UINT dest_ip)
{
bool is_host_ip = false;
UINT64 now;
LIST *new_list = NULL;
// Validate arguments
if (v == NULL)
{
return false;
}
now = Tick64();
Lock(v->HostIPCacheLock);
{
// Check if cache needs refresh (every 60 seconds or if not initialized)
if (v->HostIPAddressCache == NULL || now >= v->HostIPCacheExpires)
{
// Get new list while holding the lock to prevent multiple threads from refreshing
new_list = GetHostIPAddressList();
// Free old cache
if (v->HostIPAddressCache != NULL)
{
FreeHostIPAddressList(v->HostIPAddressCache);
}
// Set new cache with TTL
v->HostIPAddressCache = new_list;
v->HostIPCacheExpires = now + HOST_IP_CACHE_TTL_MS;
}
// Check if dest_ip matches any cached host IP
if (v->HostIPAddressCache != NULL)
{
UINT i;
IP dest_ip_obj;
UINTToIP(&dest_ip_obj, dest_ip);
for (i = 0; i < LIST_NUM(v->HostIPAddressCache); i++)
{
IP *host_ip = LIST_DATA(v->HostIPAddressCache, i);
if (IsIP4(host_ip) && CmpIpAddr(&dest_ip_obj, host_ip) == 0)
{
is_host_ip = true;
break;
}
}
}
}
Unlock(v->HostIPCacheLock);
return is_host_ip;
}
// Communication of ICMP towards the Internet
void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
{
@ -1270,15 +1209,6 @@ void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UIN
return;
}
// Check if destination is the host's own IP address
// When Native NAT tries to send packets to the host's own IP, the OS routing
// may fail or behave unexpectedly. Drop such packets to avoid issues.
if (IsDestinationHostOwnIP(v, dest_ip))
{
// Destination is the host's own IP - drop the packet
return;
}
t = v->NativeNat;
old_icmp_header = (ICMP_HEADER *)icmp_data;
@ -1421,15 +1351,6 @@ void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT
return;
}
// Check if destination is the host's own IP address
// When Native NAT tries to send packets to the host's own IP, the OS routing
// may fail or behave unexpectedly. Drop such packets to avoid issues.
if (IsDestinationHostOwnIP(v, dest_ip))
{
// Destination is the host's own IP - drop the packet
return;
}
t = v->NativeNat;
// Search whether there is an existing session
@ -1528,15 +1449,6 @@ void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT
return;
}
// Check if destination is the host's own IP address
// When Native NAT tries to send packets to the host's own IP, the OS routing
// may fail or behave unexpectedly. Drop such packets to avoid issues.
if (IsDestinationHostOwnIP(v, dest_ip))
{
// Destination is the host's own IP - drop the packet
return;
}
t = v->NativeNat;
// Search whether there is an existing session
@ -10281,13 +10193,6 @@ void Virtual_Free(VH *v)
LockVirtual(v);
{
// Free host IP cache
if (v->HostIPAddressCache != NULL)
{
FreeHostIPAddressList(v->HostIPAddressCache);
v->HostIPAddressCache = NULL;
}
// Release the IP combining list
FreeIpCombineList(v);
@ -10322,9 +10227,6 @@ void Virtual_Free(VH *v)
}
UnlockVirtual(v);
// Release the host IP cache lock
DeleteLock(v->HostIPCacheLock);
// Release the logger
FreeLog(v->Logger);
}
@ -10455,11 +10357,6 @@ VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_
v->nat = nat;
// Initialize host IP cache for Native NAT
v->HostIPAddressCache = NULL;
v->HostIPCacheExpires = 0;
v->HostIPCacheLock = NewLock();
// Examine whether ICMP Raw Socket can be created
s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
if (s != NULL)

View File

@ -313,11 +313,6 @@ struct VH
HUB_OPTION *HubOption; // Pointer to the Virtual HUB options
NATIVE_NAT *NativeNat; // Native NAT
// Host IP cache for Native NAT packet filtering
LIST *HostIPAddressCache; // Cached list of host IP addresses
UINT64 HostIPCacheExpires; // When the cache expires (tick64)
LOCK *HostIPCacheLock; // Lock for cache access
};
// Virtual host option

View File

@ -4761,7 +4761,7 @@ static void MY_SHA0_Transform(MY_SHA0_CTX* ctx) {
UCHAR* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
UINT tmp = *p++ << 24;
UINT tmp = (UINT)*p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;

View File

@ -63,7 +63,7 @@ static int ydays[] =
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
static UINT current_num_thread = 0;
static COUNTER *current_num_thread = NULL;
static UINT cached_number_of_cpus = 0;
@ -776,6 +776,7 @@ void InitThreading()
{
thread_pool = NewSk();
thread_count = NewCounter();
current_num_thread = NewCounter();
}
// Release of thread pool
@ -821,6 +822,9 @@ void FreeThreading()
DeleteCounter(thread_count);
thread_count = NULL;
DeleteCounter(current_num_thread);
current_num_thread = NULL;
}
// Thread pool procedure
@ -1028,9 +1032,9 @@ THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
Wait(pd->InitFinishEvent, INFINITE);
current_num_thread++;
Inc(current_num_thread);
// Debug("current_num_thread = %u\n", current_num_thread);
// Debug("current_num_thread = %u\n", Count(current_num_thread));
return ret;
}
@ -1055,8 +1059,8 @@ void CleanupThread(THREAD *t)
Free(t);
current_num_thread--;
//Debug("current_num_thread = %u\n", current_num_thread);
Dec(current_num_thread);
//Debug("current_num_thread = %u\n", Count(current_num_thread));
}
// Release thread (pool)

View File

@ -470,6 +470,7 @@ LIST *LoadLangList()
b = ReadDump(filename);
if (b == NULL)
{
FreeLangList(o);
return NULL;
}

View File

@ -139,6 +139,7 @@ void Tick64Thread(THREAD *thread, void *param)
{
UINT tick;
UINT64 tick64;
bool halt;
#ifndef OS_WIN32
tick = TickRealtime(); // Get the current system clock
@ -228,7 +229,13 @@ void Tick64Thread(THREAD *thread, void *param)
n = 0;
}
if (tk64->Halt)
Lock(tk64->TickLock);
{
halt = tk64->Halt;
}
Unlock(tk64->TickLock);
if (halt)
{
break;
}
@ -286,7 +293,11 @@ void FreeTick64()
}
// Termination process
Lock(tk64->TickLock);
{
tk64->Halt = true;
}
Unlock(tk64->TickLock);
Set(halt_tick_event);
WaitThread(tk64->Thread, INFINITE);
ReleaseThread(tk64->Thread);

View File

@ -2140,9 +2140,13 @@ void UnixMemoryFree(void *addr)
// SIGCHLD handler
void UnixSigChldHandler(int sig)
{
int old_errno = errno;
// Recall the zombie processes
while (waitpid(-1, NULL, WNOHANG) > 0);
signal(SIGCHLD, UnixSigChldHandler);
errno = old_errno;
}
// Disable core dump

File diff suppressed because it is too large Load Diff