1 https://bugzilla.gnome.org/show_bug.cgi?id=697264 |
|
2 https://git.gnome.org/browse/libxml2/commit/?id=5fe9e9ed1ccf217e11bd3cb99b1c6bb10cc96ba3 |
|
3 |
|
4 From 5fe9e9ed1ccf217e11bd3cb99b1c6bb10cc96ba3 Mon Sep 17 00:00:00 2001 |
|
5 From: Daniel Veillard <[email protected]> |
|
6 Date: Fri, 05 Apr 2013 15:10:41 +0000 |
|
7 Subject: Remove risk of lockup in dictionary initialization |
|
8 |
|
9 Reported by Petr Sumbera <[email protected]> |
|
10 Two threads entering xmlInitializeDict concurently could lead |
|
11 to a lockup due to multiple initializations of the lock used. |
|
12 To avoid this problem move this to a new private function |
|
13 called from xmlOnceInit() and deprecate the old initalizer. |
|
14 Since threaded programs must call xmlInitParser() and this |
|
15 will lead to dereference of private data and the call to |
|
16 xmlOnceInit() guaranteed to be unique this should be safe now. |
|
17 --- |
|
18 diff --git a/dict.c b/dict.c |
|
19 index 164c7f2..5f71d55 100644 |
|
20 --- a/dict.c |
|
21 +++ b/dict.c |
|
22 @@ -151,13 +151,28 @@ static unsigned int rand_seed = 0; |
|
23 * xmlInitializeDict: |
|
24 * |
|
25 * Do the dictionary mutex initialization. |
|
26 - * this function is not thread safe, initialization should |
|
27 - * preferably be done once at startup |
|
28 + * this function is deprecated |
|
29 * |
|
30 * Returns 0 if initialization was already done, and 1 if that |
|
31 * call led to the initialization |
|
32 */ |
|
33 int xmlInitializeDict(void) { |
|
34 + return(0); |
|
35 +} |
|
36 + |
|
37 +/** |
|
38 + * __xmlInitializeDict: |
|
39 + * |
|
40 + * This function is not public |
|
41 + * Do the dictionary mutex initialization. |
|
42 + * this function is not thread safe, initialization should |
|
43 + * normally be done once at setup when called from xmlOnceInit() |
|
44 + * we may also land in this code if thread support is not compiled in |
|
45 + * |
|
46 + * Returns 0 if initialization was already done, and 1 if that |
|
47 + * call led to the initialization |
|
48 + */ |
|
49 +int __xmlInitializeDict(void) { |
|
50 if (xmlDictInitialized) |
|
51 return(1); |
|
52 |
|
53 @@ -183,7 +198,7 @@ int __xmlRandom(void) { |
|
54 int ret; |
|
55 |
|
56 if (xmlDictInitialized == 0) |
|
57 - xmlInitializeDict(); |
|
58 + __xmlInitializeDict(); |
|
59 |
|
60 xmlRMutexLock(xmlDictMutex); |
|
61 #ifdef HAVE_RAND_R |
|
62 @@ -522,7 +537,7 @@ xmlDictCreate(void) { |
|
63 xmlDictPtr dict; |
|
64 |
|
65 if (!xmlDictInitialized) |
|
66 - if (!xmlInitializeDict()) |
|
67 + if (!__xmlInitializeDict()) |
|
68 return(NULL); |
|
69 |
|
70 #ifdef DICT_DEBUG_PATTERNS |
|
71 @@ -590,7 +605,7 @@ xmlDictCreateSub(xmlDictPtr sub) { |
|
72 int |
|
73 xmlDictReference(xmlDictPtr dict) { |
|
74 if (!xmlDictInitialized) |
|
75 - if (!xmlInitializeDict()) |
|
76 + if (!__xmlInitializeDict()) |
|
77 return(-1); |
|
78 |
|
79 if (dict == NULL) return -1; |
|
80 @@ -754,7 +769,7 @@ xmlDictFree(xmlDictPtr dict) { |
|
81 return; |
|
82 |
|
83 if (!xmlDictInitialized) |
|
84 - if (!xmlInitializeDict()) |
|
85 + if (!__xmlInitializeDict()) |
|
86 return; |
|
87 |
|
88 /* decrement the counter, it may be shared by a parser and docs */ |
|
89 diff --git a/libxml.h b/libxml.h |
|
90 index 7558b5f..2da9044 100644 |
|
91 --- a/libxml.h |
|
92 +++ b/libxml.h |
|
93 @@ -84,6 +84,8 @@ void __xmlGlobalInitMutexLock(void); |
|
94 void __xmlGlobalInitMutexUnlock(void); |
|
95 void __xmlGlobalInitMutexDestroy(void); |
|
96 |
|
97 +int __xmlInitializeDict(void); |
|
98 + |
|
99 #if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME) |
|
100 /* |
|
101 * internal thread safe random function |
|
102 diff --git a/threads.c b/threads.c |
|
103 index c8414e1..f2f2703 100644 |
|
104 --- a/threads.c |
|
105 +++ b/threads.c |
|
106 @@ -954,6 +954,7 @@ xmlOnceInit(void) |
|
107 #ifdef HAVE_PTHREAD_H |
|
108 (void) pthread_key_create(&globalkey, xmlFreeGlobalState); |
|
109 mainthread = pthread_self(); |
|
110 + __xmlInitializeDict(); |
|
111 #elif defined(HAVE_WIN32_THREADS) |
|
112 if (!run_once.done) { |
|
113 if (InterlockedIncrement(&run_once.control) == 1) { |
|
114 @@ -961,6 +962,7 @@ xmlOnceInit(void) |
|
115 globalkey = TlsAlloc(); |
|
116 #endif |
|
117 mainthread = GetCurrentThreadId(); |
|
118 + __xmlInitializeDict(); |
|
119 run_once.done = 1; |
|
120 } else { |
|
121 /* Another thread is working; give up our slice and |
|
122 @@ -974,6 +976,7 @@ xmlOnceInit(void) |
|
123 globalkey = tls_allocate(); |
|
124 tls_set(globalkey, NULL); |
|
125 mainthread = find_thread(NULL); |
|
126 + __xmlInitializeDict(); |
|
127 } else |
|
128 atomic_add(&run_once_init, -1); |
|
129 #endif |
|
130 -- |
|
131 cgit v0.9.1 |
|