aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSilvio Traversaro <silvio@traversaro.it>2019-06-11 00:19:48 +0200
committerGitHub <noreply@github.com>2019-06-11 00:19:48 +0200
commit11ff86bfab0e3baf6d17d2f2743aa735b3656ef7 (patch)
tree3984a9c029036cc902a08b91056d4a8a7cd62a01
parent1488731c810ed76589170909da9ef07f060cef46 (diff)
parente646c9ab005d6a4480fa3728ebe9c34182bfedc6 (diff)
downloaddlfcn-win32-11ff86bfab0e3baf6d17d2f2743aa735b3656ef7.tar.gz
dlfcn-win32-11ff86bfab0e3baf6d17d2f2743aa735b3656ef7.tar.bz2
dlfcn-win32-11ff86bfab0e3baf6d17d2f2743aa735b3656ef7.zip
Merge pull request #54 from pali/master
Correctly process and indicate errors
-rw-r--r--dlfcn.c127
-rw-r--r--test.c168
2 files changed, 228 insertions, 67 deletions
diff --git a/dlfcn.c b/dlfcn.c
index 993808d..ec60423 100644
--- a/dlfcn.c
+++ b/dlfcn.c
@@ -72,34 +72,36 @@ static local_object *local_search( HMODULE hModule )
72 return NULL; 72 return NULL;
73} 73}
74 74
75static void local_add( HMODULE hModule ) 75static BOOL local_add( HMODULE hModule )
76{ 76{
77 local_object *pobject; 77 local_object *pobject;
78 local_object *nobject; 78 local_object *nobject;
79 79
80 if( hModule == NULL ) 80 if( hModule == NULL )
81 return; 81 return TRUE;
82 82
83 pobject = local_search( hModule ); 83 pobject = local_search( hModule );
84 84
85 /* Do not add object again if it's already on the list */ 85 /* Do not add object again if it's already on the list */
86 if( pobject ) 86 if( pobject )
87 return; 87 return TRUE;
88 88
89 for( pobject = &first_object; pobject->next; pobject = pobject->next ); 89 for( pobject = &first_object; pobject->next; pobject = pobject->next );
90 90
91 nobject = (local_object*) malloc( sizeof( local_object ) ); 91 nobject = (local_object*) malloc( sizeof( local_object ) );
92 92
93 /* Should this be enough to fail local_add, and therefore also fail
94 * dlopen?
95 */
96 if( !nobject ) 93 if( !nobject )
97 return; 94 {
95 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
96 return FALSE;
97 }
98 98
99 pobject->next = nobject; 99 pobject->next = nobject;
100 nobject->next = NULL; 100 nobject->next = NULL;
101 nobject->previous = pobject; 101 nobject->previous = pobject;
102 nobject->hModule = hModule; 102 nobject->hModule = hModule;
103
104 return TRUE;
103} 105}
104 106
105static void local_rem( HMODULE hModule ) 107static void local_rem( HMODULE hModule )
@@ -240,51 +242,73 @@ void *dlopen( const char *file, int mode )
240 HANDLE hCurrentProc; 242 HANDLE hCurrentProc;
241 DWORD dwProcModsBefore, dwProcModsAfter; 243 DWORD dwProcModsBefore, dwProcModsAfter;
242 char lpFileName[MAX_PATH]; 244 char lpFileName[MAX_PATH];
243 size_t i; 245 size_t i, len;
244 246
245 /* MSDN says backslashes *must* be used instead of forward slashes. */ 247 len = strlen( file );
246 for( i = 0 ; i < sizeof(lpFileName) - 1 ; i ++ ) 248
249 if( len >= sizeof( lpFileName ) )
247 { 250 {
248 if( !file[i] ) 251 SetLastError( ERROR_FILENAME_EXCED_RANGE );
249 break; 252 save_err_str( file );
250 else if( file[i] == '/' ) 253 hModule = NULL;
251 lpFileName[i] = '\\';
252 else
253 lpFileName[i] = file[i];
254 } 254 }
255 lpFileName[i] = '\0'; 255 else
256 {
257 /* MSDN says backslashes *must* be used instead of forward slashes. */
258 for( i = 0; i < len; i++ )
259 {
260 if( file[i] == '/' )
261 lpFileName[i] = '\\';
262 else
263 lpFileName[i] = file[i];
264 }
265 lpFileName[len] = '\0';
256 266
257 hCurrentProc = GetCurrentProcess( ); 267 hCurrentProc = GetCurrentProcess( );
258 268
259 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) 269 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 )
260 dwProcModsBefore = 0; 270 dwProcModsBefore = 0;
261 271
262 /* POSIX says the search path is implementation-defined. 272 /* POSIX says the search path is implementation-defined.
263 * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely 273 * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
264 * to UNIX's search paths (start with system folders instead of current 274 * to UNIX's search paths (start with system folders instead of current
265 * folder). 275 * folder).
266 */ 276 */
267 hModule = LoadLibraryExA(lpFileName, NULL, 277 hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
268 LOAD_WITH_ALTERED_SEARCH_PATH ); 278
269 279 if( !hModule )
270 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) 280 {
271 dwProcModsAfter = 0; 281 save_err_str( lpFileName );
272 282 }
273 /* If the object was loaded with RTLD_LOCAL, add it to list of local 283 else
274 * objects, so that its symbols cannot be retrieved even if the handle for 284 {
275 * the original program file is passed. POSIX says that if the same 285 if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 )
276 * file is specified in multiple invocations, and any of them are 286 dwProcModsAfter = 0;
277 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the 287
278 * symbols will remain global. If number of loaded modules was not 288 /* If the object was loaded with RTLD_LOCAL, add it to list of local
279 * changed after calling LoadLibraryEx(), it means that library was 289 * objects, so that its symbols cannot be retrieved even if the handle for
280 * already loaded. 290 * the original program file is passed. POSIX says that if the same
281 */ 291 * file is specified in multiple invocations, and any of them are
282 if( !hModule ) 292 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
283 save_err_str( lpFileName ); 293 * symbols will remain global. If number of loaded modules was not
284 else if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) 294 * changed after calling LoadLibraryEx(), it means that library was
285 local_add( hModule ); 295 * already loaded.
286 else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) 296 */
287 local_rem( hModule ); 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 }
310 }
311 }
288 } 312 }
289 313
290 /* Return to previous state of the error-mode bit flags. */ 314 /* Return to previous state of the error-mode bit flags. */
@@ -353,10 +377,17 @@ void *dlsym( void *handle, const char *name )
353 size_t sLen; 377 size_t sLen;
354 sLen = VirtualQueryEx( hCurrentProc, _ReturnAddress(), &info, sizeof( info ) ); 378 sLen = VirtualQueryEx( hCurrentProc, _ReturnAddress(), &info, sizeof( info ) );
355 if( sLen != sizeof( info ) ) 379 if( sLen != sizeof( info ) )
380 {
381 if( sLen != 0 )
382 SetLastError( ERROR_INVALID_PARAMETER );
356 goto end; 383 goto end;
384 }
357 hCaller = (HMODULE) info.AllocationBase; 385 hCaller = (HMODULE) info.AllocationBase;
358 if(!hCaller) 386 if( !hCaller )
387 {
388 SetLastError( ERROR_INVALID_PARAMETER );
359 goto end; 389 goto end;
390 }
360 } 391 }
361 392
362 if( handle != RTLD_NEXT ) 393 if( handle != RTLD_NEXT )
@@ -414,6 +445,8 @@ void *dlsym( void *handle, const char *name )
414end: 445end:
415 if( symbol == NULL ) 446 if( symbol == NULL )
416 { 447 {
448 if( GetLastError() == 0 )
449 SetLastError( ERROR_PROC_NOT_FOUND );
417 save_err_str( name ); 450 save_err_str( name );
418 } 451 }
419 452
diff --git a/test.c b/test.c
index 814aca1..0070f8c 100644
--- a/test.c
+++ b/test.c
@@ -83,6 +83,11 @@ int main()
83 int (*nonexistentfunction)( void ); 83 int (*nonexistentfunction)( void );
84 int ret; 84 int ret;
85 HMODULE library3; 85 HMODULE library3;
86 char toolongfile[32767];
87 DWORD code;
88 char nonlibraryfile[MAX_PATH];
89 HANDLE tempfile;
90 DWORD dummy;
86 91
87#ifdef _DEBUG 92#ifdef _DEBUG
88 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 93 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
@@ -93,6 +98,112 @@ int main()
93 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); 98 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
94#endif 99#endif
95 100
101 ret = GetTempPathA( sizeof( nonlibraryfile ) - sizeof( "temp.dll" ), nonlibraryfile );
102 if( ret == 0 || ret > sizeof( nonlibraryfile ) - sizeof( "temp.dll" ) )
103 {
104 printf( "ERROR\tGetTempPath failed\n" );
105 RETURN_ERROR;
106 }
107
108 memcpy( nonlibraryfile + ret, "temp.dll", sizeof( "temp.dll" ) );
109
110 tempfile = CreateFileA( (LPCSTR) nonlibraryfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
111 if( tempfile == INVALID_HANDLE_VALUE )
112 {
113 printf( "ERROR\tCannot create temporary file %s: %lu\n", nonlibraryfile, (unsigned long)GetLastError( ) );
114 RETURN_ERROR;
115 }
116
117 WriteFile( tempfile, "test content", 12, &dummy, NULL );
118
119 CloseHandle( tempfile );
120
121 library3 = LoadLibraryA( nonlibraryfile );
122 code = GetLastError( );
123 if( library3 )
124 {
125 printf( "ERROR\tNon-library file %s was opened via WINAPI\n", nonlibraryfile );
126 CloseHandle( library3 );
127 DeleteFileA( nonlibraryfile );
128 RETURN_ERROR;
129 }
130 else if( code != ERROR_BAD_EXE_FORMAT )
131 {
132 printf( "ERROR\tNon-library file %s was processed via WINAPI: %lu\n", nonlibraryfile, (unsigned long)code );
133 DeleteFileA( nonlibraryfile );
134 RETURN_ERROR;
135 }
136 else
137 printf( "SUCCESS\tCould not open non-library file %s via WINAPI: %lu\n", nonlibraryfile, (unsigned long)code );
138
139 library = dlopen( nonlibraryfile, RTLD_GLOBAL );
140 if( library )
141 {
142 printf( "ERROR\tNon-library file %s was opened via dlopen\n", nonlibraryfile );
143 dlclose( library );
144 DeleteFileA( nonlibraryfile );
145 RETURN_ERROR;
146 }
147 error = dlerror( );
148 if( !error )
149 {
150 printf( "ERROR\tNo error from dlopen for non-library file\n" );
151 DeleteFileA( nonlibraryfile );
152 RETURN_ERROR;
153 }
154 else
155 printf( "SUCCESS\tCould not open non-library file %s: %s\n", nonlibraryfile, error );
156
157 DeleteFileA( nonlibraryfile );
158
159 library = dlopen( "nonexistentfile.dll", RTLD_GLOBAL );
160 if( library )
161 {
162 printf( "ERROR\tNon-existent file nonexistentfile.dll was opened via dlopen\n" );
163 RETURN_ERROR;
164 }
165 error = dlerror( );
166 if( !error )
167 {
168 printf( "ERROR\tNo error from dlopen for non-existent file\n" );
169 RETURN_ERROR;
170 }
171 else
172 printf( "SUCCESS\tCould not open non-existent file nonexistentfile.dll: %s\n", error );
173
174 memset( toolongfile, 'X', sizeof( toolongfile ) - 5 );
175 memcpy( toolongfile + sizeof( toolongfile ) - 5, ".dll", 5 );
176
177 library = dlopen( toolongfile, RTLD_GLOBAL );
178 if( library )
179 {
180 printf( "ERROR\tFile with too long file name was opened via dlopen\n" );
181 RETURN_ERROR;
182 }
183 error = dlerror( );
184 if( !error )
185 {
186 printf( "ERROR\tNo error from dlopen for file with too long file name\n" );
187 RETURN_ERROR;
188 }
189 else
190 printf( "SUCCESS\tCould not open file with too long file name: %s\n", error );
191
192 library3 = LoadLibraryA( toolongfile );
193 code = GetLastError( );
194 if( library3 )
195 {
196 printf( "ERROR\tFile with too long file name was opened via WINAPI\n" );
197 RETURN_ERROR;
198 }
199 else if( code != ERROR_FILENAME_EXCED_RANGE )
200 {
201 printf( "ERROR\tFile with too long file name was processed via WINAPI: %lu\n", (unsigned long)code );
202 RETURN_ERROR;
203 }
204 else
205 printf( "SUCCESS\tCould not open file with too long file name via WINAPI: %lu\n", (unsigned long)code );
206
96 library2 = dlopen( "testdll2.dll", RTLD_GLOBAL ); 207 library2 = dlopen( "testdll2.dll", RTLD_GLOBAL );
97 if( !library2 ) 208 if( !library2 )
98 { 209 {
@@ -201,11 +312,14 @@ int main()
201 CLOSE_GLOBAL; 312 CLOSE_GLOBAL;
202 RETURN_ERROR; 313 RETURN_ERROR;
203 } 314 }
204 else { 315 error = dlerror( );
205 error = dlerror( ); 316 if( !error )
206 printf( "SUCCESS\tCould not get nonexistent symbol from library handle: %s\n", 317 {
207 error ? error : "" ); 318 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
319 RETURN_ERROR;
208 } 320 }
321 else
322 printf( "SUCCESS\tCould not get nonexistent symbol from library handle: %s\n", error );
209 323
210 function = dlsym( global, "function" ); 324 function = dlsym( global, "function" );
211 if( !function ) 325 if( !function )
@@ -231,11 +345,14 @@ int main()
231 CLOSE_GLOBAL; 345 CLOSE_GLOBAL;
232 RETURN_ERROR; 346 RETURN_ERROR;
233 } 347 }
234 else { 348 error = dlerror( );
235 error = dlerror( ); 349 if( !error )
236 printf( "SUCCESS\tCould not get nonexistent symbol from global handle: %s\n", 350 {
237 error ? error : "" ); 351 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
352 RETURN_ERROR;
238 } 353 }
354 else
355 printf( "SUCCESS\tCould not get nonexistent symbol from global handle: %s\n", error );
239 356
240 ret = dlclose( library ); 357 ret = dlclose( library );
241 if( ret ) 358 if( ret )
@@ -293,11 +410,14 @@ int main()
293 CLOSE_GLOBAL; 410 CLOSE_GLOBAL;
294 RETURN_ERROR; 411 RETURN_ERROR;
295 } 412 }
296 else { 413 error = dlerror( );
297 error = dlerror( ); 414 if( !error )
298 printf( "SUCCESS\tCould not get nonexistent symbol from library handle: %s\n", 415 {
299 error ? error : "" ); 416 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
417 RETURN_ERROR;
300 } 418 }
419 else
420 printf( "SUCCESS\tCould not get nonexistent symbol from library handle: %s\n", error );
301 421
302 function = dlsym( global, "function" ); 422 function = dlsym( global, "function" );
303 if( function ) 423 if( function )
@@ -321,11 +441,14 @@ int main()
321 CLOSE_GLOBAL; 441 CLOSE_GLOBAL;
322 RETURN_ERROR; 442 RETURN_ERROR;
323 } 443 }
324 else { 444 error = dlerror( );
325 error = dlerror( ); 445 if( !error )
326 printf( "SUCCESS\tDid not get nonexistent local symbol from global handle: %s\n", 446 {
327 error ? error : "" ); 447 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
448 RETURN_ERROR;
328 } 449 }
450 else
451 printf( "SUCCESS\tDid not get nonexistent local symbol from global handle: %s\n", error );
329 452
330 library = dlopen( "testdll.dll", RTLD_GLOBAL ); 453 library = dlopen( "testdll.dll", RTLD_GLOBAL );
331 if( !library ) 454 if( !library )
@@ -363,10 +486,15 @@ int main()
363 CLOSE_GLOBAL; 486 CLOSE_GLOBAL;
364 RETURN_ERROR; 487 RETURN_ERROR;
365 } 488 }
366 else { 489 error = dlerror( );
367 error = dlerror( ); 490 if( !error )
368 printf( "SUCCESS\tCould not get nonexistent symbol from global handle: %s\n", 491 {
369 error ? error : "" ); 492 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
493 RETURN_ERROR;
494 }
495 else
496 {
497 printf( "SUCCESS\tCould not get nonexistent symbol from global handle: %s\n", error );
370 498
371 /* Test that the second call to dlerror() returns null as in the specs 499 /* Test that the second call to dlerror() returns null as in the specs
372 See https://github.com/dlfcn-win32/dlfcn-win32/issues/34 */ 500 See https://github.com/dlfcn-win32/dlfcn-win32/issues/34 */