diff options
| author | Paul Eggert | 2017-07-14 16:18:37 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-07-14 16:36:18 -0700 |
| commit | 05b8b866993b957f5fd575846cf8ea3035e60f7e (patch) | |
| tree | 7d25217ee1f4c409cb217c52a6bd152dda675b8a /src/fns.c | |
| parent | 8b64a80a56c0e15d3313a45022ae60b33dbb4bff (diff) | |
| download | emacs-05b8b866993b957f5fd575846cf8ea3035e60f7e.tar.gz emacs-05b8b866993b957f5fd575846cf8ea3035e60f7e.zip | |
GnuTLS integer-overflow and style fixes
This tweaks the recently-added GnuTLS improvements so that
they avoid some integer-overflow problems and follow typical
Emacs style a bit better.
* configure.ac (HAVE_GNUTLS3_HMAC, HAVE_GNUTLS3_AEAD)
(HAVE_GNUTLS3_CIPHER): Use AC_CACHE_CHECK so that the
configure-time results are displayed.
* src/fns.c (extract_data_from_object): Return char *, not char
const *, since one gnutls caller wants a non-const pointer. Use
CONSP rather than !NILP when testing for conses. Use CAR_SAFE
instead of rolling our own code. Prefer signed types to unsigned
when either will do. Report problems for lengths out of range,
instead of silently mishandling them.
* src/gnutls.c (emacs_gnutls_strerror): New function, to simplify
callers. All callers of gnutls_sterror changed.
(Fgnutls_boot): Check for integers out of range rather than
silently truncating them.
(gnutls_symmetric_aead): Check for integer overflow in size
calculations.
(gnutls_symmetric_aead, Fgnutls_macs, Fgnutls_digests):
Prefer signed to unsigned integers where either will do.
(gnutls_symmetric_aead, gnutls_symmetric):
Work even if ptrdiff_t is wider than ‘long’.
(gnutls_symmetric, Fgnutls_hash_mac, Fgnutls_hash_digest):
Check for integer overflow in algorithm selection.
Diffstat (limited to 'src/fns.c')
| -rw-r--r-- | src/fns.c | 49 |
1 files changed, 22 insertions, 27 deletions
| @@ -46,10 +46,6 @@ static void sort_vector_copy (Lisp_Object, ptrdiff_t, | |||
| 46 | enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; | 46 | enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; |
| 47 | static bool internal_equal (Lisp_Object, Lisp_Object, | 47 | static bool internal_equal (Lisp_Object, Lisp_Object, |
| 48 | enum equal_kind, int, Lisp_Object); | 48 | enum equal_kind, int, Lisp_Object); |
| 49 | static Lisp_Object | ||
| 50 | secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, | ||
| 51 | Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror, | ||
| 52 | Lisp_Object binary); | ||
| 53 | 49 | ||
| 54 | DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, | 50 | DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, |
| 55 | doc: /* Return the argument unchanged. */ | 51 | doc: /* Return the argument unchanged. */ |
| @@ -4767,29 +4763,24 @@ DEFUN ("secure-hash-algorithms", Fsecure_hash_algorithms, | |||
| 4767 | (BUFFER-OR-STRING-OR-SYMBOL START END CODING-SYSTEM NOERROR) which behave as | 4763 | (BUFFER-OR-STRING-OR-SYMBOL START END CODING-SYSTEM NOERROR) which behave as |
| 4768 | specified with `secure-hash' and in Info node | 4764 | specified with `secure-hash' and in Info node |
| 4769 | `(elisp)Format of GnuTLS Cryptography Inputs'. */ | 4765 | `(elisp)Format of GnuTLS Cryptography Inputs'. */ |
| 4770 | const char* | 4766 | char * |
| 4771 | extract_data_from_object (Lisp_Object spec, | 4767 | extract_data_from_object (Lisp_Object spec, |
| 4772 | ptrdiff_t *start_byte, | 4768 | ptrdiff_t *start_byte, |
| 4773 | ptrdiff_t *end_byte) | 4769 | ptrdiff_t *end_byte) |
| 4774 | { | 4770 | { |
| 4775 | ptrdiff_t size, start_char = 0, end_char = 0; | 4771 | Lisp_Object object = XCAR (spec); |
| 4776 | register EMACS_INT b, e; | ||
| 4777 | register struct buffer *bp; | ||
| 4778 | EMACS_INT temp; | ||
| 4779 | 4772 | ||
| 4780 | Lisp_Object object = XCAR (spec); | 4773 | if (CONSP (spec)) spec = XCDR (spec); |
| 4774 | Lisp_Object start = CAR_SAFE (spec); | ||
| 4781 | 4775 | ||
| 4782 | if (! NILP (spec)) spec = XCDR (spec); | 4776 | if (CONSP (spec)) spec = XCDR (spec); |
| 4783 | Lisp_Object start = (CONSP (spec)) ? XCAR (spec) : Qnil; | 4777 | Lisp_Object end = CAR_SAFE (spec); |
| 4784 | 4778 | ||
| 4785 | if (! NILP (spec)) spec = XCDR (spec); | 4779 | if (CONSP (spec)) spec = XCDR (spec); |
| 4786 | Lisp_Object end = (CONSP (spec)) ? XCAR (spec) : Qnil; | 4780 | Lisp_Object coding_system = CAR_SAFE (spec); |
| 4787 | 4781 | ||
| 4788 | if (! NILP (spec)) spec = XCDR (spec); | 4782 | if (CONSP (spec)) spec = XCDR (spec); |
| 4789 | Lisp_Object coding_system = (CONSP (spec)) ? XCAR (spec) : Qnil; | 4783 | Lisp_Object noerror = CAR_SAFE (spec); |
| 4790 | |||
| 4791 | if (! NILP (spec)) spec = XCDR (spec); | ||
| 4792 | Lisp_Object noerror = (CONSP (spec)) ? XCAR (spec) : Qnil; | ||
| 4793 | 4784 | ||
| 4794 | if (STRINGP (object)) | 4785 | if (STRINGP (object)) |
| 4795 | { | 4786 | { |
| @@ -4817,7 +4808,7 @@ extract_data_from_object (Lisp_Object spec, | |||
| 4817 | if (STRING_MULTIBYTE (object)) | 4808 | if (STRING_MULTIBYTE (object)) |
| 4818 | object = code_convert_string (object, coding_system, Qnil, 1, 0, 1); | 4809 | object = code_convert_string (object, coding_system, Qnil, 1, 0, 1); |
| 4819 | 4810 | ||
| 4820 | size = SCHARS (object); | 4811 | ptrdiff_t size = SCHARS (object), start_char, end_char; |
| 4821 | validate_subarray (object, start, end, size, &start_char, &end_char); | 4812 | validate_subarray (object, start, end, size, &start_char, &end_char); |
| 4822 | 4813 | ||
| 4823 | *start_byte = !start_char ? 0 : string_char_to_byte (object, start_char); | 4814 | *start_byte = !start_char ? 0 : string_char_to_byte (object, start_char); |
| @@ -4828,12 +4819,13 @@ extract_data_from_object (Lisp_Object spec, | |||
| 4828 | else if (BUFFERP (object)) | 4819 | else if (BUFFERP (object)) |
| 4829 | { | 4820 | { |
| 4830 | struct buffer *prev = current_buffer; | 4821 | struct buffer *prev = current_buffer; |
| 4822 | EMACS_INT b, e; | ||
| 4831 | 4823 | ||
| 4832 | record_unwind_current_buffer (); | 4824 | record_unwind_current_buffer (); |
| 4833 | 4825 | ||
| 4834 | CHECK_BUFFER (object); | 4826 | CHECK_BUFFER (object); |
| 4835 | 4827 | ||
| 4836 | bp = XBUFFER (object); | 4828 | struct buffer *bp = XBUFFER (object); |
| 4837 | set_buffer_internal (bp); | 4829 | set_buffer_internal (bp); |
| 4838 | 4830 | ||
| 4839 | if (NILP (start)) | 4831 | if (NILP (start)) |
| @@ -4853,7 +4845,11 @@ extract_data_from_object (Lisp_Object spec, | |||
| 4853 | } | 4845 | } |
| 4854 | 4846 | ||
| 4855 | if (b > e) | 4847 | if (b > e) |
| 4856 | temp = b, b = e, e = temp; | 4848 | { |
| 4849 | EMACS_INT temp = b; | ||
| 4850 | b = e; | ||
| 4851 | e = temp; | ||
| 4852 | } | ||
| 4857 | 4853 | ||
| 4858 | if (!(BEGV <= b && e <= ZV)) | 4854 | if (!(BEGV <= b && e <= ZV)) |
| 4859 | args_out_of_range (start, end); | 4855 | args_out_of_range (start, end); |
| @@ -4932,14 +4928,13 @@ extract_data_from_object (Lisp_Object spec, | |||
| 4932 | else if (EQ (object, Qiv_auto)) | 4928 | else if (EQ (object, Qiv_auto)) |
| 4933 | { | 4929 | { |
| 4934 | #ifdef HAVE_GNUTLS3 | 4930 | #ifdef HAVE_GNUTLS3 |
| 4935 | // Format: (iv-auto REQUIRED-LENGTH) | 4931 | /* Format: (iv-auto REQUIRED-LENGTH). */ |
| 4936 | 4932 | ||
| 4937 | if (! INTEGERP (start)) | 4933 | if (! NATNUMP (start)) |
| 4938 | error ("Without a length, iv-auto can't be used. See manual."); | 4934 | error ("Without a length, iv-auto can't be used. See manual."); |
| 4939 | else | 4935 | else |
| 4940 | { | 4936 | { |
| 4941 | /* Make sure the value of "start" doesn't change. */ | 4937 | EMACS_INT start_hold = XFASTINT (start); |
| 4942 | size_t start_hold = XUINT (start); | ||
| 4943 | object = make_uninit_string (start_hold); | 4938 | object = make_uninit_string (start_hold); |
| 4944 | gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold); | 4939 | gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold); |
| 4945 | 4940 | ||
| @@ -4971,7 +4966,7 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, | |||
| 4971 | 4966 | ||
| 4972 | Lisp_Object spec = list5 (object, start, end, coding_system, noerror); | 4967 | Lisp_Object spec = list5 (object, start, end, coding_system, noerror); |
| 4973 | 4968 | ||
| 4974 | const char* input = extract_data_from_object (spec, &start_byte, &end_byte); | 4969 | const char *input = extract_data_from_object (spec, &start_byte, &end_byte); |
| 4975 | 4970 | ||
| 4976 | if (input == NULL) | 4971 | if (input == NULL) |
| 4977 | error ("secure_hash: failed to extract data from object, aborting!"); | 4972 | error ("secure_hash: failed to extract data from object, aborting!"); |