diff options
author | Pali Rohár <pali.rohar@gmail.com> | 2019-05-23 20:23:58 +0200 |
---|---|---|
committer | Pali Rohár <pali.rohar@gmail.com> | 2019-05-23 20:23:58 +0200 |
commit | 207311ceba4f8e2ebab27ead6e07dfecef392383 (patch) | |
tree | 63a78a42a0318d25650d0106224e8320f1c43202 | |
parent | 44589dba9c663eaeed5dbf55a02984133b9ab822 (diff) | |
download | dlfcn-win32-207311ceba4f8e2ebab27ead6e07dfecef392383.tar.gz dlfcn-win32-207311ceba4f8e2ebab27ead6e07dfecef392383.tar.bz2 dlfcn-win32-207311ceba4f8e2ebab27ead6e07dfecef392383.zip |
Correctly process and indicate error when file name is too long
-rw-r--r-- | dlfcn.c | 102 |
1 files changed, 55 insertions, 47 deletions
@@ -242,63 +242,71 @@ void *dlopen( const char *file, int mode ) | |||
242 | HANDLE hCurrentProc; | 242 | HANDLE hCurrentProc; |
243 | DWORD dwProcModsBefore, dwProcModsAfter; | 243 | DWORD dwProcModsBefore, dwProcModsAfter; |
244 | char lpFileName[MAX_PATH]; | 244 | char lpFileName[MAX_PATH]; |
245 | size_t i; | 245 | size_t i, len; |
246 | |||
247 | /* MSDN says backslashes *must* be used instead of forward slashes. */ | ||
248 | for( i = 0 ; i < sizeof(lpFileName) - 1 ; i ++ ) | ||
249 | { | ||
250 | if( !file[i] ) | ||
251 | break; | ||
252 | else if( file[i] == '/' ) | ||
253 | lpFileName[i] = '\\'; | ||
254 | else | ||
255 | lpFileName[i] = file[i]; | ||
256 | } | ||
257 | lpFileName[i] = '\0'; | ||
258 | |||
259 | hCurrentProc = GetCurrentProcess( ); | ||
260 | 246 | ||
261 | if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) | 247 | len = strlen( file ); |
262 | dwProcModsBefore = 0; | ||
263 | 248 | ||
264 | /* POSIX says the search path is implementation-defined. | 249 | if( len >= sizeof( lpFileName ) ) |
265 | * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely | ||
266 | * to UNIX's search paths (start with system folders instead of current | ||
267 | * folder). | ||
268 | */ | ||
269 | hModule = LoadLibraryExA(lpFileName, NULL, | ||
270 | LOAD_WITH_ALTERED_SEARCH_PATH ); | ||
271 | |||
272 | if( !hModule ) | ||
273 | { | 250 | { |
274 | save_err_str( lpFileName ); | 251 | SetLastError( ERROR_FILENAME_EXCED_RANGE ); |
252 | save_err_str( file ); | ||
253 | hModule = NULL; | ||
275 | } | 254 | } |
276 | else | 255 | else |
277 | { | 256 | { |
278 | if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) | 257 | /* MSDN says backslashes *must* be used instead of forward slashes. */ |
279 | dwProcModsAfter = 0; | 258 | for( i = 0; i < len; i++ ) |
280 | 259 | { | |
281 | /* If the object was loaded with RTLD_LOCAL, add it to list of local | 260 | if( file[i] == '/' ) |
282 | * objects, so that its symbols cannot be retrieved even if the handle for | 261 | lpFileName[i] = '\\'; |
283 | * the original program file is passed. POSIX says that if the same | 262 | else |
284 | * file is specified in multiple invocations, and any of them are | 263 | lpFileName[i] = file[i]; |
285 | * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the | 264 | } |
286 | * symbols will remain global. If number of loaded modules was not | 265 | lpFileName[len] = '\0'; |
287 | * changed after calling LoadLibraryEx(), it means that library was | 266 | |
288 | * already loaded. | 267 | hCurrentProc = GetCurrentProcess( ); |
268 | |||
269 | if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) | ||
270 | dwProcModsBefore = 0; | ||
271 | |||
272 | /* POSIX says the search path is implementation-defined. | ||
273 | * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely | ||
274 | * to UNIX's search paths (start with system folders instead of current | ||
275 | * folder). | ||
289 | */ | 276 | */ |
290 | if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) | 277 | hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); |
278 | |||
279 | if( !hModule ) | ||
291 | { | 280 | { |
292 | if( !local_add( hModule ) ) | 281 | save_err_str( lpFileName ); |
293 | { | ||
294 | save_err_str( lpFileName ); | ||
295 | FreeLibrary( hModule ); | ||
296 | hModule = NULL; | ||
297 | } | ||
298 | } | 282 | } |
299 | else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) | 283 | else |
300 | { | 284 | { |
301 | local_rem( hModule ); | 285 | if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) |
286 | dwProcModsAfter = 0; | ||
287 | |||
288 | /* If the object was loaded with RTLD_LOCAL, add it to list of local | ||
289 | * objects, so that its symbols cannot be retrieved even if the handle for | ||
290 | * the original program file is passed. POSIX says that if the same | ||
291 | * file is specified in multiple invocations, and any of them are | ||
292 | * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the | ||
293 | * symbols will remain global. If number of loaded modules was not | ||
294 | * changed after calling LoadLibraryEx(), it means that library was | ||
295 | * already loaded. | ||
296 | */ | ||
297 | if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) | ||
298 | { | ||
299 | if( !local_add( hModule ) ) | ||
300 | { | ||
301 | save_err_str( lpFileName ); | ||
302 | FreeLibrary( hModule ); | ||
303 | hModule = NULL; | ||
304 | } | ||
305 | } | ||
306 | else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) | ||
307 | { | ||
308 | local_rem( hModule ); | ||
309 | } | ||
302 | } | 310 | } |
303 | } | 311 | } |
304 | } | 312 | } |