Skip to content

Commit 1d30971

Browse files
committed
Bump vendored deps: Mongoose 7.21, SQLite 3.51.3, mimalloc 3.2.8
Mongoose 7.20 → 7.21: Fixes 3 CVEs disclosed 2026-04-02: - CVE-2026-5244: preauth RCE via TLS heap buffer overflow - CVE-2026-5245: mDNS stack overflow RCE (34-byte UDP packet) - CVE-2026-5246: mTLS bypass with P-384 certificates SQLite 3.49.1 → 3.51.3: Fixes WAL-reset database corruption bug (we use WAL mode). Also fixes nested EXISTS query errors, POSIX lock deadlock, and FTS5 memory error. mimalloc 2.1.9 → 3.2.8 (v2 → v3): Eliminated thread-local segments for better cross-thread sharing, lower fragmentation, faster TLS on Windows, improved calloc. API change: mi_option_eager_commit → mi_option_arena_eager_commit. Linux kernel benchmark: 1:42 (no regression). All 2718 tests pass.
1 parent 09ce20a commit 1d30971

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+19625
-10581
lines changed

src/foundation/mem.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ void cbm_mem_init(double ram_fraction) {
116116
ram_fraction = DEFAULT_RAM_FRACTION;
117117
}
118118

119-
/* Reduce upfront memory: don't eagerly commit segments */
120-
mi_option_set(mi_option_eager_commit, 0);
119+
/* Reduce upfront memory: don't eagerly commit arenas */
120+
mi_option_set(mi_option_arena_eager_commit, 0);
121121

122122
cbm_system_info_t info = cbm_system_info();
123123
g_budget = (size_t)((double)info.total_ram * ram_fraction);
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/* ----------------------------------------------------------------------------
2+
Copyright (c) 2024-2025, Microsoft Research, Daan Leijen
3+
This is free software; you can redistribute it and/or modify it under the
4+
terms of the MIT license. A copy of the license can be found in the file
5+
"LICENSE" at the root of this distribution.
6+
-----------------------------------------------------------------------------*/
7+
#pragma once
8+
#ifndef MIMALLOC_STATS_H
9+
#define MIMALLOC_STATS_H
10+
11+
#include <mimalloc.h>
12+
#include <stdint.h>
13+
14+
#define MI_STAT_VERSION 4 // increased on every backward incompatible change
15+
16+
// alignment for atomic fields
17+
#if defined(_MSC_VER)
18+
#define mi_decl_align(a) __declspec(align(a))
19+
#elif defined(__GNUC__)
20+
#define mi_decl_align(a) __attribute__((aligned(a)))
21+
#elif __cplusplus >= 201103L
22+
#define mi_decl_align(a) alignas(a)
23+
#else
24+
#define mi_decl_align(a)
25+
#endif
26+
27+
28+
// count allocation over time
29+
typedef struct mi_stat_count_s {
30+
int64_t total; // total allocated
31+
int64_t peak; // peak allocation
32+
int64_t current; // current allocation
33+
} mi_stat_count_t;
34+
35+
// counters only increase
36+
typedef struct mi_stat_counter_s {
37+
int64_t total; // total count
38+
} mi_stat_counter_t;
39+
40+
#define MI_STAT_FIELDS() \
41+
MI_STAT_COUNT(pages) /* count of mimalloc pages */ \
42+
MI_STAT_COUNT(reserved) /* reserved memory bytes */ \
43+
MI_STAT_COUNT(committed) /* committed bytes */ \
44+
MI_STAT_COUNTER(reset) /* reset bytes */ \
45+
MI_STAT_COUNTER(purged) /* purged bytes */ \
46+
MI_STAT_COUNT(page_committed) /* committed memory inside pages */ \
47+
MI_STAT_COUNT(pages_abandoned) /* abandonded pages count */ \
48+
MI_STAT_COUNT(threads) /* number of threads */ \
49+
MI_STAT_COUNT(malloc_normal) /* allocated bytes <= MI_LARGE_OBJ_SIZE_MAX */ \
50+
MI_STAT_COUNT(malloc_huge) /* allocated bytes in huge pages */ \
51+
MI_STAT_COUNT(malloc_requested) /* malloc requested bytes */ \
52+
\
53+
MI_STAT_COUNTER(mmap_calls) \
54+
MI_STAT_COUNTER(commit_calls) \
55+
MI_STAT_COUNTER(reset_calls) \
56+
MI_STAT_COUNTER(purge_calls) \
57+
MI_STAT_COUNTER(arena_count) /* number of memory arena's */ \
58+
MI_STAT_COUNTER(malloc_normal_count) /* number of blocks <= MI_LARGE_OBJ_SIZE_MAX */ \
59+
MI_STAT_COUNTER(malloc_huge_count) /* number of huge bloks */ \
60+
MI_STAT_COUNTER(malloc_guarded_count) /* number of allocations with guard pages */ \
61+
\
62+
/* internal statistics */ \
63+
MI_STAT_COUNTER(arena_rollback_count) \
64+
MI_STAT_COUNTER(arena_purges) \
65+
MI_STAT_COUNTER(pages_extended) /* number of page extensions */ \
66+
MI_STAT_COUNTER(pages_retire) /* number of pages that are retired */ \
67+
MI_STAT_COUNTER(page_searches) /* total pages searched for a fresh page */ \
68+
MI_STAT_COUNTER(page_searches_count) /* searched count for a fresh page */ \
69+
/* only on v1 and v2 */ \
70+
MI_STAT_COUNT(segments) \
71+
MI_STAT_COUNT(segments_abandoned) \
72+
MI_STAT_COUNT(segments_cache) \
73+
MI_STAT_COUNT(_segments_reserved) \
74+
/* only on v3 */ \
75+
MI_STAT_COUNT(heaps) \
76+
MI_STAT_COUNTER(pages_reclaim_on_alloc) \
77+
MI_STAT_COUNTER(pages_reclaim_on_free) \
78+
MI_STAT_COUNTER(pages_reabandon_full) \
79+
MI_STAT_COUNTER(pages_unabandon_busy_wait)
80+
81+
// Size bins for chunks
82+
typedef enum mi_chunkbin_e {
83+
MI_CBIN_SMALL, // slice_count == 1
84+
MI_CBIN_OTHER, // slice_count: any other from the other bins, and 1 <= slice_count <= MI_BCHUNK_BITS
85+
MI_CBIN_MEDIUM, // slice_count == 8
86+
MI_CBIN_LARGE, // slice_count == MI_SIZE_BITS (only used if MI_ENABLE_LARGE_PAGES is 1)
87+
MI_CBIN_HUGE, // slice_count > MI_BCHUNK_BITS
88+
MI_CBIN_NONE, // no bin assigned yet (the chunk is completely free)
89+
MI_CBIN_COUNT
90+
} mi_chunkbin_t;
91+
92+
93+
// Define the statistics structure
94+
#define MI_BIN_HUGE (73U) // see types.h
95+
#define MI_STAT_COUNT(stat) mi_stat_count_t stat;
96+
#define MI_STAT_COUNTER(stat) mi_stat_counter_t stat;
97+
98+
typedef struct mi_stats_s
99+
{
100+
size_t size; // size of the mi_stats_t structure
101+
size_t version;
102+
103+
mi_decl_align(8) MI_STAT_FIELDS()
104+
105+
// future extension
106+
mi_stat_count_t _stat_reserved[4];
107+
mi_stat_counter_t _stat_counter_reserved[4];
108+
109+
// size segregated statistics
110+
mi_stat_count_t malloc_bins[MI_BIN_HUGE+1]; // allocation per size bin
111+
mi_stat_count_t page_bins[MI_BIN_HUGE+1]; // pages allocated per size bin
112+
mi_stat_count_t chunk_bins[MI_CBIN_COUNT]; // chunks per page sizes
113+
} mi_stats_t;
114+
115+
#undef MI_STAT_COUNT
116+
#undef MI_STAT_COUNTER
117+
118+
// helper
119+
#define mi_stats_t_decl(name) mi_stats_t name = { 0 }; name.size = sizeof(mi_stats_t); name.version = MI_STAT_VERSION;
120+
121+
// Exported definitions
122+
#ifdef __cplusplus
123+
extern "C" {
124+
#endif
125+
126+
// stats from a heap
127+
mi_decl_export bool mi_heap_stats_get(mi_heap_t* heap, mi_stats_t* stats) mi_attr_noexcept;
128+
mi_decl_export char* mi_heap_stats_get_json(mi_heap_t* heap, size_t buf_size, char* buf) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL
129+
mi_decl_export void mi_heap_stats_print_out(mi_heap_t* heap, mi_output_fun* out, void* arg) mi_attr_noexcept;
130+
131+
// stats from a subprocess and its heaps aggregated
132+
mi_decl_export bool mi_subproc_stats_get(mi_subproc_id_t subproc_id, mi_stats_t* stats) mi_attr_noexcept;
133+
mi_decl_export char* mi_subproc_stats_get_json(mi_subproc_id_t subproc_id, size_t buf_size, char* buf) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL
134+
mi_decl_export void mi_subproc_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun* out, void* arg) mi_attr_noexcept;
135+
// print subprocess and all its heap stats segregated
136+
mi_decl_export void mi_subproc_heap_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun* out, void* arg) mi_attr_noexcept;
137+
138+
// stats aggregated for the current subprocess and all its heaps.
139+
mi_decl_export bool mi_stats_get(mi_stats_t* stats) mi_attr_noexcept;
140+
mi_decl_export char* mi_stats_get_json(size_t buf_size, char* buf) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL
141+
mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
142+
143+
// add the stats of the heap to the subprocess and clear the heap stats
144+
mi_decl_export void mi_heap_stats_merge_to_subproc(mi_heap_t* heap);
145+
146+
// stats from the subprocess without aggregating its heaps
147+
mi_decl_export bool mi_subproc_stats_get_exclusive(mi_subproc_id_t subproc_id, mi_stats_t* stats) mi_attr_noexcept;
148+
149+
mi_decl_export char* mi_stats_as_json(mi_stats_t* stats, size_t buf_size, char* buf) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL
150+
mi_decl_export size_t mi_stats_get_bin_size(size_t bin) mi_attr_noexcept;
151+
152+
#ifdef __cplusplus
153+
}
154+
#endif
155+
156+
#endif // MIMALLOC_STATS_H

0 commit comments

Comments
 (0)