mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[misc] harden usage of uprintf()
* Passing a non-formatting buffer as first parameter of uprintf() can lead to an exception if this buffer happens to contain a '%' character, so usage of uprintf() with string buffers that may contain '%' should be sanitized. * Also drop the _uprintf/_uprintfs aliases as they are no longer required.
This commit is contained in:
		
							parent
							
								
									1a3a155e8c
								
							
						
					
					
						commit
						fffd4d1160
					
				
					 12 changed files with 37 additions and 31 deletions
				
			
		|  | @ -29,9 +29,9 @@ struct error_table { | ||||||
| struct et_list; | struct et_list; | ||||||
| 
 | 
 | ||||||
| /* For use with Rufus */ | /* For use with Rufus */ | ||||||
| extern void _uprintf(const char *format, ...); | extern void uprintf(const char *format, ...); | ||||||
| #define VA_ARGS(...) , ##__VA_ARGS__ | #define VA_ARGS(...) , ##__VA_ARGS__ | ||||||
| #define com_err(src, err, fmt, ...) _uprintf("%s: [%08X] " # fmt, src?src:"ext2fs", err - EXT2_ET_BASE VA_ARGS(__VA_ARGS__)) | #define com_err(src, err, fmt, ...) uprintf("%s: [%08X] " # fmt, src?src:"ext2fs", err - EXT2_ET_BASE VA_ARGS(__VA_ARGS__)) | ||||||
| 
 | 
 | ||||||
| extern char const *error_message (long); | extern char const *error_message (long); | ||||||
| extern void (*com_err_hook) (const char *, long, const char *, va_list); | extern void (*com_err_hook) (const char *, long, const char *, va_list); | ||||||
|  |  | ||||||
|  | @ -1290,7 +1290,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive) | ||||||
| 		} | 		} | ||||||
| 		assert((uintptr_t)sec_buf % SelectedDrive.SectorSize == 0); | 		assert((uintptr_t)sec_buf % SelectedDrive.SectorSize == 0); | ||||||
| 		sec_buf_pos = 0; | 		sec_buf_pos = 0; | ||||||
| 		bled_init(_uprintf, NULL, sector_write, update_progress, NULL, &FormatStatus); | 		bled_init(uprintf, NULL, sector_write, update_progress, NULL, &FormatStatus); | ||||||
| 		bled_ret = bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, img_report.compression_type); | 		bled_ret = bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, img_report.compression_type); | ||||||
| 		bled_exit(); | 		bled_exit(); | ||||||
| 		uprintfs("\r\n"); | 		uprintfs("\r\n"); | ||||||
|  |  | ||||||
|  | @ -535,7 +535,8 @@ void PrintStatusInfo(BOOL info, BOOL debug, unsigned int duration, int msg_id, . | ||||||
| 		safe_vsnprintf(buf, MSG_LEN, format, args); | 		safe_vsnprintf(buf, MSG_LEN, format, args); | ||||||
| 		va_end(args); | 		va_end(args); | ||||||
| 		buf[MSG_LEN - 1] = '\0'; | 		buf[MSG_LEN - 1] = '\0'; | ||||||
| 		uprintf(buf); | 		// buf may(?) containt a '%' so don't feed it as a naked format string
 | ||||||
|  | 		uprintf("%s", buf); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -945,7 +945,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) | ||||||
| 		free(sig); | 		free(sig); | ||||||
| 		uprintf("Download signature is valid ✓"); | 		uprintf("Download signature is valid ✓"); | ||||||
| 		uncompressed_size = *((uint64_t*)&compressed[5]); | 		uncompressed_size = *((uint64_t*)&compressed[5]); | ||||||
| 		if ((uncompressed_size < 1 * MB) && (bled_init(_uprintf, NULL, NULL, NULL, NULL, &FormatStatus) >= 0)) { | 		if ((uncompressed_size < 1 * MB) && (bled_init(uprintf, NULL, NULL, NULL, NULL, &FormatStatus) >= 0)) { | ||||||
| 			fido_script = malloc((size_t)uncompressed_size); | 			fido_script = malloc((size_t)uncompressed_size); | ||||||
| 			size = bled_uncompress_from_buffer_to_buffer(compressed, dwCompressedSize, fido_script, (size_t)uncompressed_size, BLED_COMPRESSION_LZMA); | 			size = bled_uncompress_from_buffer_to_buffer(compressed, dwCompressedSize, fido_script, (size_t)uncompressed_size, BLED_COMPRESSION_LZMA); | ||||||
| 			bled_exit(); | 			bled_exit(); | ||||||
|  |  | ||||||
|  | @ -493,7 +493,8 @@ static DWORD WINAPI SearchProcessThread(LPVOID param) | ||||||
| 			// If we're switching process and found a match, print it
 | 			// If we're switching process and found a match, print it
 | ||||||
| 			if (bFound) { | 			if (bFound) { | ||||||
| 				static_sprintf (tmp, "● [%06u] %s (%s)", (uint32_t)pid[cur_pid], cmdline, access_rights_str[access_rights & 0x7]); | 				static_sprintf (tmp, "● [%06u] %s (%s)", (uint32_t)pid[cur_pid], cmdline, access_rights_str[access_rights & 0x7]); | ||||||
| 				vuprintf(tmp); | 				// tmp may contain a '%' so don't feed it as a naked format string
 | ||||||
|  | 				vuprintf("%s", tmp); | ||||||
| 				StrArrayAdd(&BlockingProcess, tmp, TRUE); | 				StrArrayAdd(&BlockingProcess, tmp, TRUE); | ||||||
| 				bFound = FALSE; | 				bFound = FALSE; | ||||||
| 				access_rights = 0; | 				access_rights = 0; | ||||||
|  |  | ||||||
|  | @ -2255,7 +2255,8 @@ DWORD CheckDriveAccess(DWORD dwTimeOut, BOOL bPrompt) | ||||||
| 			proceed = FALSE; | 			proceed = FALSE; | ||||||
| 			uprintf("Found potentially blocking process(es) against %s:", &PhysicalPath[4]); | 			uprintf("Found potentially blocking process(es) against %s:", &PhysicalPath[4]); | ||||||
| 			for (j = 0; j < BlockingProcess.Index; j++) | 			for (j = 0; j < BlockingProcess.Index; j++) | ||||||
| 				uprintf(BlockingProcess.String[j]); | 				// BlockingProcess.String[j] may contain a '%' so don't feed it as a naked format string
 | ||||||
|  | 				uprintf("%s", BlockingProcess.String[j]); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -2275,7 +2276,8 @@ DWORD CheckDriveAccess(DWORD dwTimeOut, BOOL bPrompt) | ||||||
| 				proceed = FALSE; | 				proceed = FALSE; | ||||||
| 				uprintf("Found potentially blocking process(es) against %s", drive_name); | 				uprintf("Found potentially blocking process(es) against %s", drive_name); | ||||||
| 				for (j = 0; j < BlockingProcess.Index; j++) | 				for (j = 0; j < BlockingProcess.Index; j++) | ||||||
| 					uprintf(BlockingProcess.String[j]); | 					// BlockingProcess.String[j] may contain a '%' so don't feed it as a naked format string
 | ||||||
|  | 					uprintf("%s", BlockingProcess.String[j]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -3547,7 +3549,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 			if (list_params) { | 			if (list_params) { | ||||||
| 				uprintf("Command line arguments:"); | 				uprintf("Command line arguments:"); | ||||||
| 				for (i = 1; i < argc; i++) | 				for (i = 1; i < argc; i++) | ||||||
| 					uprintf(argv[i]); | 					// argv[i] may contain a '%' so don't feed it as a naked format string.
 | ||||||
|  | 					uprintf("%s", argv[i]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -172,20 +172,18 @@ static __inline void static_repchr(char* p, char s, char r) { | ||||||
| #define to_unix_path(str) static_repchr(str, '\\', '/') | #define to_unix_path(str) static_repchr(str, '\\', '/') | ||||||
| #define to_windows_path(str) static_repchr(str, '/', '\\') | #define to_windows_path(str) static_repchr(str, '/', '\\') | ||||||
| 
 | 
 | ||||||
| extern void _uprintf(const char *format, ...); | extern void uprintf(const char *format, ...); | ||||||
| extern void _uprintfs(const char *str); | extern void uprintfs(const char *str); | ||||||
| #define uprintf(...) _uprintf(__VA_ARGS__) | #define vuprintf(...) do { if (verbose) uprintf(__VA_ARGS__); } while(0) | ||||||
| #define uprintfs(s) _uprintfs(s) | #define vvuprintf(...) do { if (verbose > 1) uprintf(__VA_ARGS__); } while(0) | ||||||
| #define vuprintf(...) do { if (verbose) _uprintf(__VA_ARGS__); } while(0) | #define suprintf(...) do { if (!bSilent) uprintf(__VA_ARGS__); } while(0) | ||||||
| #define vvuprintf(...) do { if (verbose > 1) _uprintf(__VA_ARGS__); } while(0) | #define uuprintf(...) do { if (usb_debug) uprintf(__VA_ARGS__); } while(0) | ||||||
| #define suprintf(...) do { if (!bSilent) _uprintf(__VA_ARGS__); } while(0) |  | ||||||
| #define uuprintf(...) do { if (usb_debug) _uprintf(__VA_ARGS__); } while(0) |  | ||||||
| #define ubprintf(...) do { safe_sprintf(&ubuffer[ubuffer_pos], UBUFFER_SIZE - ubuffer_pos - 4, __VA_ARGS__); \ | #define ubprintf(...) do { safe_sprintf(&ubuffer[ubuffer_pos], UBUFFER_SIZE - ubuffer_pos - 4, __VA_ARGS__); \ | ||||||
| 	ubuffer_pos = strlen(ubuffer); ubuffer[ubuffer_pos++] = '\r'; ubuffer[ubuffer_pos++] = '\n'; \ | 	ubuffer_pos = strlen(ubuffer); ubuffer[ubuffer_pos++] = '\r'; ubuffer[ubuffer_pos++] = '\n'; \ | ||||||
| 	ubuffer[ubuffer_pos] = 0; } while(0) | 	ubuffer[ubuffer_pos] = 0; } while(0) | ||||||
| #define ubflush() do { if (ubuffer_pos) uprintf("%s", ubuffer); ubuffer_pos = 0; } while(0) | #define ubflush() do { if (ubuffer_pos) uprintf("%s", ubuffer); ubuffer_pos = 0; } while(0) | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
| #define duprintf(...) _uprintf(__VA_ARGS__) | #define duprintf uprintf | ||||||
| #else | #else | ||||||
| #define duprintf(...) | #define duprintf(...) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -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 3.23.2025" | CAPTION "Rufus 3.23.2026" | ||||||
| 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 | ||||||
|  | @ -392,8 +392,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 3,23,2025,0 |  FILEVERSION 3,23,2026,0 | ||||||
|  PRODUCTVERSION 3,23,2025,0 |  PRODUCTVERSION 3,23,2026,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -411,13 +411,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", "3.23.2025" |             VALUE "FileVersion", "3.23.2026" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2023 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-3.23.exe" |             VALUE "OriginalFilename", "rufus-3.23.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.23.2025" |             VALUE "ProductVersion", "3.23.2026" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
|  | @ -762,8 +762,8 @@ DWORD RunCommand(const char* cmd, const char* dir, BOOL log) | ||||||
| 					output = malloc(dwAvail + 1); | 					output = malloc(dwAvail + 1); | ||||||
| 					if ((output != NULL) && (ReadFile(hOutputRead, output, dwAvail, &dwRead, NULL)) && (dwRead != 0)) { | 					if ((output != NULL) && (ReadFile(hOutputRead, output, dwAvail, &dwRead, NULL)) && (dwRead != 0)) { | ||||||
| 						output[dwAvail] = 0; | 						output[dwAvail] = 0; | ||||||
| 						// coverity[tainted_string]
 | 						// output may contain a '%' so don't feed it as a naked format string
 | ||||||
| 						uprintf(output); | 						uprintf("%s", output); | ||||||
| 					} | 					} | ||||||
| 					free(output); | 					free(output); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Rufus: The Reliable USB Formatting Utility |  * Rufus: The Reliable USB Formatting Utility | ||||||
|  * Standard User I/O Routines (logging, status, error, etc.) |  * Standard User I/O Routines (logging, status, error, etc.) | ||||||
|  |  * Copyright © 2011-2023 Pete Batard <pete@akeo.ie> | ||||||
|  * Copyright © 2020 Mattiwatti <mattiwatti@gmail.com> |  * Copyright © 2020 Mattiwatti <mattiwatti@gmail.com> | ||||||
|  * Copyright © 2011-2021 Pete Batard <pete@akeo.ie> |  | ||||||
|  * |  * | ||||||
|  * This program is free software: you can redistribute it and/or modify |  * This program is free software: you can redistribute it and/or modify | ||||||
|  * it under the terms of the GNU General Public License as published by |  * it under the terms of the GNU General Public License as published by | ||||||
|  | @ -46,7 +46,7 @@ HWND hStatus; | ||||||
| size_t ubuffer_pos = 0; | size_t ubuffer_pos = 0; | ||||||
| char ubuffer[UBUFFER_SIZE];	// Buffer for ubpushf() messages we don't log right away
 | char ubuffer[UBUFFER_SIZE];	// Buffer for ubpushf() messages we don't log right away
 | ||||||
| 
 | 
 | ||||||
| void _uprintf(const char *format, ...) | void uprintf(const char *format, ...) | ||||||
| { | { | ||||||
| 	static char buf[4096]; | 	static char buf[4096]; | ||||||
| 	char* p = buf; | 	char* p = buf; | ||||||
|  | @ -82,7 +82,7 @@ void _uprintf(const char *format, ...) | ||||||
| 	free(wbuf); | 	free(wbuf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void _uprintfs(const char* str) | void uprintfs(const char* str) | ||||||
| { | { | ||||||
| 	wchar_t* wstr; | 	wchar_t* wstr; | ||||||
| 	wstr = utf8_to_wchar(str); | 	wstr = utf8_to_wchar(str); | ||||||
|  |  | ||||||
|  | @ -211,7 +211,7 @@ static BOOL IsCompressedBootableImage(const char* path) | ||||||
| 			if (buf == NULL) | 			if (buf == NULL) | ||||||
| 				return FALSE; | 				return FALSE; | ||||||
| 			FormatStatus = 0; | 			FormatStatus = 0; | ||||||
| 			bled_init(_uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | 			bled_init(uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | ||||||
| 			dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); | 			dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); | ||||||
| 			bled_exit(); | 			bled_exit(); | ||||||
| 			if (dc != MBR_SIZE) { | 			if (dc != MBR_SIZE) { | ||||||
|  |  | ||||||
|  | @ -673,6 +673,8 @@ BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | ||||||
| 	static_sprintf(cmd, "%s\\bcdboot.exe %s\\Windows /v /f %s /s %s", sysnative_dir, drive_name, | 	static_sprintf(cmd, "%s\\bcdboot.exe %s\\Windows /v /f %s /s %s", sysnative_dir, drive_name, | ||||||
| 		HAS_BOOTMGR_BIOS(img_report) ? (HAS_BOOTMGR_EFI(img_report) ? "ALL" : "BIOS") : "UEFI", | 		HAS_BOOTMGR_BIOS(img_report) ? (HAS_BOOTMGR_EFI(img_report) ? "ALL" : "BIOS") : "UEFI", | ||||||
| 		(use_esp) ? ms_efi : drive_name); | 		(use_esp) ? ms_efi : drive_name); | ||||||
|  | 	// I don't believe we can ever have a stray '%' in cmd, but just in case...
 | ||||||
|  | 	assert(strchr(cmd, '%') == NULL); | ||||||
| 	uprintf(cmd); | 	uprintf(cmd); | ||||||
| 	if (RunCommand(cmd, sysnative_dir, usb_debug) != 0) { | 	if (RunCommand(cmd, sysnative_dir, usb_debug) != 0) { | ||||||
| 		// Try to continue... but report a failure
 | 		// Try to continue... but report a failure
 | ||||||
|  | @ -698,6 +700,7 @@ BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | ||||||
| 	uprintf("Disabling use of the Windows Recovery Environment using command:"); | 	uprintf("Disabling use of the Windows Recovery Environment using command:"); | ||||||
| 	static_sprintf(cmd, "%s\\bcdedit.exe /store %s\\EFI\\Microsoft\\Boot\\BCD /set {default} recoveryenabled no", | 	static_sprintf(cmd, "%s\\bcdedit.exe /store %s\\EFI\\Microsoft\\Boot\\BCD /set {default} recoveryenabled no", | ||||||
| 		sysnative_dir, (use_esp) ? ms_efi : drive_name); | 		sysnative_dir, (use_esp) ? ms_efi : drive_name); | ||||||
|  | 	assert(strchr(cmd, '%') == NULL); | ||||||
| 	uprintf(cmd); | 	uprintf(cmd); | ||||||
| 	RunCommand(cmd, sysnative_dir, usb_debug); | 	RunCommand(cmd, sysnative_dir, usb_debug); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue