aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2011-03-15 00:04:00 -0700
committerPaul Eggert2011-03-15 00:04:00 -0700
commit15206ed9236f4957cb62a0cfbd5397cf8f0cb76b (patch)
treec5b79dc24fd900342aaed46555ef28480014f502 /src
parent4a6bea268fbac2fd64018374652f5b2c9b04b4fd (diff)
downloademacs-15206ed9236f4957cb62a0cfbd5397cf8f0cb76b.tar.gz
emacs-15206ed9236f4957cb62a0cfbd5397cf8f0cb76b.zip
Fix a race condition diagnosed by gcc -Wsequence-point (Bug#8254).
An expression of the form (DOWNCASE (x) == DOWNCASE (y)), found in dired.c's scmp function, had undefined behavior. * lisp.h (DOWNCASE_TABLE, UPCASE_TABLE, DOWNCASE, UPPERCASEP): (NOCASEP, LOWERCASEP, UPCASE, UPCASE1): Move from here ... * buffer.h: ... to here, because these macros use current_buffer, and the new implementation with inline functions needs to have current_buffer in scope now, rather than later when the macros are used. (downcase, upcase1): New static inline functions. (DOWNCASE, UPCASE1): Reimplement using these functions. This avoids undefined behavior in expressions like DOWNCASE (x) == DOWNCASE (y), which previously suffered from race conditions in accessing the global variables case_temp1 and case_temp2. * casetab.c (case_temp1, case_temp2): Remove; no longer needed. * lisp.h (case_temp1, case_temp2): Remove their decls. * character.h (ASCII_CHAR_P): Move from here ... * lisp.h: ... to here, so that the inline functions mentioned above can use them.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog21
-rw-r--r--src/buffer.h43
-rw-r--r--src/casetab.c6
-rw-r--r--src/character.h3
-rw-r--r--src/lisp.h47
5 files changed, 67 insertions, 53 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 7468af4c725..7e873e3d85d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,26 @@
12011-03-15 Paul Eggert <eggert@cs.ucla.edu> 12011-03-15 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Fix a race condition diagnosed by gcc -Wsequence-point (Bug#8254).
4 An expression of the form (DOWNCASE (x) == DOWNCASE (y)), found in
5 dired.c's scmp function, had undefined behavior.
6 * lisp.h (DOWNCASE_TABLE, UPCASE_TABLE, DOWNCASE, UPPERCASEP):
7 (NOCASEP, LOWERCASEP, UPCASE, UPCASE1): Move from here ...
8 * buffer.h: ... to here, because these macros use current_buffer,
9 and the new implementation with inline functions needs to have
10 current_buffer in scope now, rather than later when the macros
11 are used.
12 (downcase, upcase1): New static inline functions.
13 (DOWNCASE, UPCASE1): Reimplement using these functions.
14 This avoids undefined behavior in expressions like
15 DOWNCASE (x) == DOWNCASE (y), which previously suffered
16 from race conditions in accessing the global variables
17 case_temp1 and case_temp2.
18 * casetab.c (case_temp1, case_temp2): Remove; no longer needed.
19 * lisp.h (case_temp1, case_temp2): Remove their decls.
20 * character.h (ASCII_CHAR_P): Move from here ...
21 * lisp.h: ... to here, so that the inline functions mentioned
22 above can use them.
23
3 * dired.c (directory_files_internal_unwind): Now static. 24 * dired.c (directory_files_internal_unwind): Now static.
4 25
5 * fileio.c (file_name_as_directory, directory_file_name): 26 * fileio.c (file_name_as_directory, directory_file_name):
diff --git a/src/buffer.h b/src/buffer.h
index 0975d2e3adc..996e4e59c27 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1026,4 +1026,47 @@ extern int last_per_buffer_idx;
1026 1026
1027#define PER_BUFFER_VALUE(BUFFER, OFFSET) \ 1027#define PER_BUFFER_VALUE(BUFFER, OFFSET) \
1028 (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER))) 1028 (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER)))
1029
1030/* Current buffer's map from characters to lower-case characters. */
1031
1032#define DOWNCASE_TABLE BVAR (current_buffer, downcase_table)
1033
1034/* Current buffer's map from characters to upper-case characters. */
1035
1036#define UPCASE_TABLE BVAR (current_buffer, upcase_table)
1037
1038/* Downcase a character, or make no change if that cannot be done. */
1039
1040static inline EMACS_INT
1041downcase (int ch)
1042{
1043 Lisp_Object down = CHAR_TABLE_REF (DOWNCASE_TABLE, ch);
1044 return NATNUMP (down) ? XFASTINT (down) : ch;
1045}
1046#define DOWNCASE(CH) downcase (CH)
1047
1048/* 1 if CH is upper case. */
1049
1050#define UPPERCASEP(CH) (DOWNCASE (CH) != (CH))
1029 1051
1052/* 1 if CH is neither upper nor lower case. */
1053
1054#define NOCASEP(CH) (UPCASE1 (CH) == (CH))
1055
1056/* 1 if CH is lower case. */
1057
1058#define LOWERCASEP(CH) (!UPPERCASEP (CH) && !NOCASEP(CH))
1059
1060/* Upcase a character, or make no change if that cannot be done. */
1061
1062#define UPCASE(CH) (!UPPERCASEP (CH) ? UPCASE1 (CH) : (CH))
1063
1064/* Upcase a character known to be not upper case. */
1065
1066static inline EMACS_INT
1067upcase1 (int ch)
1068{
1069 Lisp_Object up = CHAR_TABLE_REF (UPCASE_TABLE, ch);
1070 return NATNUMP (up) ? XFASTINT (up) : ch;
1071}
1072#define UPCASE1(CH) upcase1 (CH)
diff --git a/src/casetab.c b/src/casetab.c
index 5207e5315ae..56f6b065358 100644
--- a/src/casetab.c
+++ b/src/casetab.c
@@ -28,11 +28,6 @@ Lisp_Object Qcase_table_p, Qcase_table;
28Lisp_Object Vascii_downcase_table, Vascii_upcase_table; 28Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
29Lisp_Object Vascii_canon_table, Vascii_eqv_table; 29Lisp_Object Vascii_canon_table, Vascii_eqv_table;
30 30
31/* Used as a temporary in DOWNCASE and other macros in lisp.h. No
32 need to mark it, since it is used only very temporarily. */
33int case_temp1;
34Lisp_Object case_temp2;
35
36static void set_canon (Lisp_Object case_table, Lisp_Object range, Lisp_Object elt); 31static void set_canon (Lisp_Object case_table, Lisp_Object range, Lisp_Object elt);
37static void set_identity (Lisp_Object table, Lisp_Object c, Lisp_Object elt); 32static void set_identity (Lisp_Object table, Lisp_Object c, Lisp_Object elt);
38static void shuffle (Lisp_Object table, Lisp_Object c, Lisp_Object elt); 33static void shuffle (Lisp_Object table, Lisp_Object c, Lisp_Object elt);
@@ -302,4 +297,3 @@ syms_of_casetab (void)
302 defsubr (&Sset_case_table); 297 defsubr (&Sset_case_table);
303 defsubr (&Sset_standard_case_table); 298 defsubr (&Sset_standard_case_table);
304} 299}
305
diff --git a/src/character.h b/src/character.h
index d29ab41557b..6d5b8110109 100644
--- a/src/character.h
+++ b/src/character.h
@@ -128,9 +128,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
128 XSETCDR ((x), tmp); \ 128 XSETCDR ((x), tmp); \
129 } while (0) 129 } while (0)
130 130
131/* Nonzero iff C is an ASCII character. */
132#define ASCII_CHAR_P(c) ((unsigned) (c) < 0x80)
133
134/* Nonzero iff C is a character of code less than 0x100. */ 131/* Nonzero iff C is a character of code less than 0x100. */
135#define SINGLE_BYTE_CHAR_P(c) ((unsigned) (c) < 0x100) 132#define SINGLE_BYTE_CHAR_P(c) ((unsigned) (c) < 0x100)
136 133
diff --git a/src/lisp.h b/src/lisp.h
index 3ba18186497..15c13e0467b 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -841,6 +841,9 @@ struct Lisp_Vector
841 841
842#endif /* not __GNUC__ */ 842#endif /* not __GNUC__ */
843 843
844/* Nonzero iff C is an ASCII character. */
845#define ASCII_CHAR_P(c) ((unsigned) (c) < 0x80)
846
844/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII 847/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
845 characters. Do not check validity of CT. */ 848 characters. Do not check validity of CT. */
846#define CHAR_TABLE_REF(CT, IDX) \ 849#define CHAR_TABLE_REF(CT, IDX) \
@@ -2041,50 +2044,6 @@ extern int pending_signals;
2041 2044
2042#define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) 2045#define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
2043 2046
2044/* Variables used locally in the following case handling macros. */
2045extern int case_temp1;
2046extern Lisp_Object case_temp2;
2047
2048/* Current buffer's map from characters to lower-case characters. */
2049
2050#define DOWNCASE_TABLE BVAR (current_buffer, downcase_table)
2051
2052/* Current buffer's map from characters to upper-case characters. */
2053
2054#define UPCASE_TABLE BVAR (current_buffer, upcase_table)
2055
2056/* Downcase a character, or make no change if that cannot be done. */
2057
2058#define DOWNCASE(CH) \
2059 ((case_temp1 = (CH), \
2060 case_temp2 = CHAR_TABLE_REF (DOWNCASE_TABLE, case_temp1), \
2061 NATNUMP (case_temp2)) \
2062 ? XFASTINT (case_temp2) : case_temp1)
2063
2064/* 1 if CH is upper case. */
2065
2066#define UPPERCASEP(CH) (DOWNCASE (CH) != (CH))
2067
2068/* 1 if CH is neither upper nor lower case. */
2069
2070#define NOCASEP(CH) (UPCASE1 (CH) == (CH))
2071
2072/* 1 if CH is lower case. */
2073
2074#define LOWERCASEP(CH) (!UPPERCASEP (CH) && !NOCASEP(CH))
2075
2076/* Upcase a character, or make no change if that cannot be done. */
2077
2078#define UPCASE(CH) (!UPPERCASEP (CH) ? UPCASE1 (CH) : (CH))
2079
2080/* Upcase a character known to be not upper case. */
2081
2082#define UPCASE1(CH) \
2083 ((case_temp1 = (CH), \
2084 case_temp2 = CHAR_TABLE_REF (UPCASE_TABLE, case_temp1), \
2085 NATNUMP (case_temp2)) \
2086 ? XFASTINT (case_temp2) : case_temp1)
2087
2088extern Lisp_Object Vascii_downcase_table, Vascii_upcase_table; 2047extern Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
2089extern Lisp_Object Vascii_canon_table, Vascii_eqv_table; 2048extern Lisp_Object Vascii_canon_table, Vascii_eqv_table;
2090 2049