1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2026-07-09 06:55:39 +00:00

Compare commits

...

2 commits

Author SHA1 Message Date
Pete Batard
b7bd966926
[wue] append " (SILENT)" to the label name when using the silent option
* Also update ChangeLog for BETA.
2026-06-17 11:23:39 +01:00
Ejigs
925a014d74
[core] fix unrestricted entity expansion and integer overflow in ezxml
* Add EZXML_MAXEXP limit (8 MB) to ezxml_decode() to prevent exponential memory growth from nested entity definitions (billion laughs attack).
* Add recursion depth limit to ezxml_ent_ok() to prevent CPU exhaustion during DTD processing of deeply nested entity definitions.
* Change _realloc() parameter from unsigned int to size_t to prevent silent truncation of allocation sizes on 64-bit builds.
* Change size calculation variables in ezxml_decode() from long to size_t/ssize_t to prevent signed integer overflow on Windows where long is 32-bit even on x64.
* Add NULL check for strchr() result before pointer arithmetic in entity expansion to prevent undefined behavior on malformed input.
* Add bounds check in ezxml_internal_dtd() entity name parsing to prevent write past buffer.
* Closes Security Advisory report https://github.com/pbatard/rufus/security/advisories/GHSA-55r2-34wg-8mv9.
2026-06-17 11:02:45 +01:00
5 changed files with 49 additions and 19 deletions

View file

@ -1,3 +1,14 @@
o Version 4.15 (2026.06.??)
Improve the guards for using the "silent" option
Improve the ability to cancel during write retries
Fix unrestricted XML entity expansion and integer overflow in ezxml parser (courtesy of Eric Sadowski)
Fix "silent" Windows installation failing at 75% in most cases
Fix a crash during boot when using UEFI:NTFS on Snapdragon X based ARM64 platforms
Fix the first WUE option always being checked by default
Fix an infinite loop when using Windows ISOs that contain multiple WIMs
Fix "Enable runtime UEFI media validation" checkbox not always being properly enabled
Other WUE improvements/fixes for OneDrive removal and username validation (with thanks to @christian8641)
o Version 4.14 (2026.04.30) o Version 4.14 (2026.04.30)
Windows User Experience improvements: Windows User Experience improvements:
- Add a "Quality of Life" option, to disable Teams, Outlook, Copilot and other Microsoft forced nuisances - Add a "Quality of Life" option, to disable Teams, Outlook, Copilot and other Microsoft forced nuisances

View file

@ -74,7 +74,7 @@ extern const int nb_steps[FS_MAX];
extern const char* md5sum_name[2]; extern const char* md5sum_name[2];
extern uint32_t dur_mins, dur_secs; extern uint32_t dur_mins, dur_secs;
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing; extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing;
extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available, has_ffu_support, use_rufus_mbr; extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available, has_ffu_support, use_rufus_mbr, append_silent;
extern char* archive_path; extern char* archive_path;
uint8_t *grub2_buf = NULL, *sec_buf = NULL; uint8_t *grub2_buf = NULL, *sec_buf = NULL;
long grub2_len; long grub2_len;
@ -1781,6 +1781,9 @@ try_clear:
} }
GetWindowTextU(hLabel, label, sizeof(label)); GetWindowTextU(hLabel, label, sizeof(label));
// Append a " (SILENT)" suffix to the label for fully unattended silent installation media.
if (append_silent && strstr(label, " (SILENT)") == NULL)
static_strcat(label, " (SILENT)");
if (fs_type < FS_EXT2) if (fs_type < FS_EXT2)
ToValidLabel(label, (fs_type == FS_FAT16) || (fs_type == FS_FAT32) || (fs_type == FS_EXFAT)); ToValidLabel(label, (fs_type == FS_FAT16) || (fs_type == FS_FAT32) || (fs_type == FS_EXFAT));
ClusterSize = (DWORD)ComboBox_GetCurItemData(hClusterSize); ClusterSize = (DWORD)ComboBox_GetCurItemData(hClusterSize);

View file

@ -131,7 +131,7 @@ BOOL usb_debug, use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALS
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE; BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE;
BOOL write_as_image = FALSE, write_as_esp = FALSE, use_vds = FALSE, ignore_boot_marker = FALSE, save_image = FALSE; BOOL write_as_image = FALSE, write_as_esp = FALSE, use_vds = FALSE, ignore_boot_marker = FALSE, save_image = FALSE;
BOOL appstore_version = FALSE, is_vds_available = TRUE, persistent_log = FALSE, has_ffu_support = FALSE; BOOL appstore_version = FALSE, is_vds_available = TRUE, persistent_log = FALSE, has_ffu_support = FALSE;
BOOL expert_mode = FALSE, use_rufus_mbr = TRUE, bcdboot_supports_ex = FALSE; BOOL expert_mode = FALSE, use_rufus_mbr = TRUE, bcdboot_supports_ex = FALSE, append_silent = FALSE;
float fScale = 1.0f; float fScale = 1.0f;
int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1, imop_win_sel = 0; int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1, imop_win_sel = 0;
int default_fs, fs_type, boot_type, partition_type, target_type; int default_fs, fs_type, boot_type, partition_type, target_type;
@ -1506,6 +1506,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0;
safe_free(grub2_buf); safe_free(grub2_buf);
append_silent = FALSE;
if (ComboBox_GetCurSel(hDeviceList) == CB_ERR) if (ComboBox_GetCurSel(hDeviceList) == CB_ERR)
goto out; goto out;
@ -1751,6 +1752,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
if (i < 0) if (i < 0)
goto out; goto out;
i = remap16(i, map, TRUE); i = remap16(i, map, TRUE);
append_silent = (i & UNATTEND_SILENT_INSTALL);
unattend_xml_path = CreateUnattendXml(arch, i); unattend_xml_path = CreateUnattendXml(arch, i);
// Remember the user preferences for the current session. // Remember the user preferences for the current session.
unattend_xml_mask &= ~(remap16(UNATTEND_FULL_MASK, map, TRUE)); unattend_xml_mask &= ~(remap16(UNATTEND_FULL_MASK, map, TRUE));

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326 IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 4.15.2389" CAPTION "Rufus 4.15.2391"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0 FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -409,8 +409,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,15,2389,0 FILEVERSION 4,15,2391,0
PRODUCTVERSION 4,15,2389,0 PRODUCTVERSION 4,15,2391,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -428,13 +428,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie" VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting" VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.15.2389" VALUE "FileVersion", "4.15.2391"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.15.exe" VALUE "OriginalFilename", "rufus-4.15.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.15.2389" VALUE "ProductVersion", "4.15.2391"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -42,8 +42,9 @@
#endif #endif
#define EZXML_NOMMAP #define EZXML_NOMMAP
#define EZXML_WS "\t\r\n " // whitespace #define EZXML_WS "\t\r\n " // whitespace
#define EZXML_ERRL 256 // maximum error string length #define EZXML_ERRL 256 // maximum error string length
#define EZXML_MAXEXP (8 * MB) // max entity expansion (to prevent "billion laughs" blowup)
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:6011) #pragma warning(disable:6011)
@ -68,7 +69,7 @@ struct ezxml_root { // additional data for the root tag
char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings
// what realloc should be doing all along // what realloc should be doing all along
static inline void* _realloc(void* ptr, unsigned int size) { static inline void* _realloc(void* ptr, size_t size) {
void* old_ptr = ptr; void* old_ptr = ptr;
ptr = realloc(ptr, size); ptr = realloc(ptr, size);
if (ptr == NULL) if (ptr == NULL)
@ -200,7 +201,8 @@ ezxml_t ezxml_err(ezxml_root_t root, char *s, const char *err, ...)
char *ezxml_decode(char *s, char **ent, char t) char *ezxml_decode(char *s, char **ent, char t)
{ {
char *e, *r = s, *m = s; char *e, *r = s, *m = s;
long b, c, d, l; ssize_t b, c, d;
size_t l, o, x = 0;
for (; *s; s++) { // normalize line endings for (; *s; s++) { // normalize line endings
while (*s == '\r') { while (*s == '\r') {
@ -214,8 +216,8 @@ char *ezxml_decode(char *s, char **ent, char t)
if (! *s) break; if (! *s) break;
else if (t != 'c' && ! strncmp(s, "&#", 2)) { // character reference else if (t != 'c' && ! strncmp(s, "&#", 2)) { // character reference
if (s[2] == 'x') c = strtol(s + 3, &e, 16); // base 16 if (s[2] == 'x') c = (ssize_t)strtoull(s + 3, &e, 16); // base 16
else c = strtol(s + 2, &e, 10); // base 10 else c = (ssize_t)strtoull(s + 2, &e, 10); // base 10
if (! c || *e != ';') { s++; continue; } // not a character ref if (! c || *e != ';') { s++; continue; } // not a character ref
if (c < 0x80) *(s++) = (char)c; // US-ASCII subset if (c < 0x80) *(s++) = (char)c; // US-ASCII subset
@ -236,10 +238,14 @@ char *ezxml_decode(char *s, char **ent, char t)
b += 2); // find entity in entity list b += 2); // find entity in entity list
if (ent[b++]) { // found a match if (ent[b++]) { // found a match
if ((c = (long)strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) { c = strlen(ent[b]);
l = (d = (long)(s - r)) + c + (long)(e ? strlen(e) : 0); // new length x += c;
if (x > EZXML_MAXEXP) break;
if ((e = strchr(s, ';')) && c - 1 > e - s) {
o = s - r;
l = o + c + (e ? strlen(e) : 0); // new length
r = (r == m) ? strcpy(malloc(l), r) : _realloc(r, l); r = (r == m) ? strcpy(malloc(l), r) : _realloc(r, l);
e = strchr((s = r + d), ';'); // fix up pointers e = strchr((s = r + o), ';'); // fix up pointers
} }
if (!e) return r; if (!e) return r;
@ -254,7 +260,7 @@ char *ezxml_decode(char *s, char **ent, char t)
if (t == '*') { // normalize spaces for non-cdata attributes if (t == '*') { // normalize spaces for non-cdata attributes
for (s = r; *s; s++) { for (s = r; *s; s++) {
if ((l = (long)strspn(s, " "))) memmove(s, s + l, strlen(s + l) + 1); if ((l = strspn(s, " "))) memmove(s, s + l, strlen(s + l) + 1);
while (*s && *s != ' ') s++; while (*s && *s != ' ') s++;
} }
if (--s >= r && *s == ' ') *s = '\0'; // trim any trailing space if (--s >= r && *s == ' ') *s = '\0'; // trim any trailing space
@ -310,19 +316,27 @@ ezxml_t ezxml_close_tag(ezxml_root_t root, char *name, char *s)
// checks for circular entity references, returns non-zero if no circular // checks for circular entity references, returns non-zero if no circular
// references are found, zero otherwise // references are found, zero otherwise
int ezxml_ent_ok(char *name, char *s, char **ent) static int ezxml_ent_ok_r(char *name, char *s, char **ent, int depth)
{ {
int i; int i;
if (depth <= 0) return 0; // treat deep nesting as circular
for (; ; s++) { for (; ; s++) {
while (*s && *s != '&') s++; // find next entity reference while (*s && *s != '&') s++; // find next entity reference
if (! *s) return 1; if (! *s) return 1;
if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref. if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref.
for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2); for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
if (ent[i] && ! ezxml_ent_ok(name, ent[i + 1], ent)) return 0; if (ent[i] && ! ezxml_ent_ok_r(name, ent[i + 1], ent, depth - 1))
return 0;
} }
} }
int ezxml_ent_ok(char *name, char *s, char **ent)
{
return ezxml_ent_ok_r(name, s, ent, 20);
}
// called when the parser finds a processing instruction // called when the parser finds a processing instruction
void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len) void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len)
{ {