diff options
| author | Chong Yidong | 2011-10-27 14:07:09 +0800 |
|---|---|---|
| committer | Chong Yidong | 2011-10-27 14:07:09 +0800 |
| commit | 9c6c6f495b8469ca5e105f5ddb02a69d1303a106 (patch) | |
| tree | 0858a59fdd543e7dca46fb6a3ab495c21c417f07 /src | |
| parent | 15de15c66d96905aa21f1781861067eebd68b24b (diff) | |
| download | emacs-9c6c6f495b8469ca5e105f5ddb02a69d1303a106.tar.gz emacs-9c6c6f495b8469ca5e105f5ddb02a69d1303a106.zip | |
Fix a memory leak in the built-in GnuTLS support.
* src/gnutls.c (emacs_gnutls_deinit): New function. Deallocate
credentials structures as well as calling gnutls_deinit.
(Fgnutls_deinit, Fgnutls_boot): Use it.
* src/process.c (make_process): Initialize GnuTLS credentials to NULL.
(deactivate_process): Call emacs_gnutls_deinit.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/gnutls.c | 89 | ||||
| -rw-r--r-- | src/gnutls.h | 1 | ||||
| -rw-r--r-- | src/process.c | 7 |
4 files changed, 61 insertions, 45 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 3caecf32049..65995d0ac92 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2011-10-27 Chong Yidong <cyd@gnu.org> | ||
| 2 | |||
| 3 | * gnutls.c (emacs_gnutls_deinit): New function. Deallocate | ||
| 4 | credentials structures as well as calling gnutls_deinit. | ||
| 5 | (Fgnutls_deinit, Fgnutls_boot): Use it. | ||
| 6 | |||
| 7 | * process.c (make_process): Initialize GnuTLS credentials to NULL. | ||
| 8 | (deactivate_process): Call emacs_gnutls_deinit. | ||
| 9 | |||
| 1 | 2011-10-27 Juanma Barranquero <lekktu@gmail.com> | 10 | 2011-10-27 Juanma Barranquero <lekktu@gmail.com> |
| 2 | 11 | ||
| 3 | * image.c (x_create_x_image_and_pixmap): | 12 | * image.c (x_create_x_image_and_pixmap): |
diff --git a/src/gnutls.c b/src/gnutls.c index 0743ef3f4ee..f836692198c 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -464,6 +464,42 @@ gnutls_make_error (int err) | |||
| 464 | return make_number (err); | 464 | return make_number (err); |
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | Lisp_Object | ||
| 468 | emacs_gnutls_deinit (Lisp_Object proc) | ||
| 469 | { | ||
| 470 | int log_level; | ||
| 471 | |||
| 472 | CHECK_PROCESS (proc); | ||
| 473 | |||
| 474 | if (XPROCESS (proc)->gnutls_p == 0) | ||
| 475 | return Qnil; | ||
| 476 | |||
| 477 | log_level = XPROCESS (proc)->gnutls_log_level; | ||
| 478 | |||
| 479 | if (XPROCESS (proc)->gnutls_x509_cred) | ||
| 480 | { | ||
| 481 | GNUTLS_LOG (2, log_level, "Deallocating x509 credentials"); | ||
| 482 | fn_gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred); | ||
| 483 | XPROCESS (proc)->gnutls_x509_cred = NULL; | ||
| 484 | } | ||
| 485 | |||
| 486 | if (XPROCESS (proc)->gnutls_anon_cred) | ||
| 487 | { | ||
| 488 | GNUTLS_LOG (2, log_level, "Deallocating anon credentials"); | ||
| 489 | fn_gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred); | ||
| 490 | XPROCESS (proc)->gnutls_anon_cred = NULL; | ||
| 491 | } | ||
| 492 | |||
| 493 | if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT) | ||
| 494 | { | ||
| 495 | fn_gnutls_deinit (XPROCESS (proc)->gnutls_state); | ||
| 496 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1; | ||
| 497 | } | ||
| 498 | |||
| 499 | XPROCESS (proc)->gnutls_p = 0; | ||
| 500 | return Qt; | ||
| 501 | } | ||
| 502 | |||
| 467 | DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0, | 503 | DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0, |
| 468 | doc: /* Return the GnuTLS init stage of process PROC. | 504 | doc: /* Return the GnuTLS init stage of process PROC. |
| 469 | See also `gnutls-boot'. */) | 505 | See also `gnutls-boot'. */) |
| @@ -551,18 +587,7 @@ DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0, | |||
| 551 | See also `gnutls-init'. */) | 587 | See also `gnutls-init'. */) |
| 552 | (Lisp_Object proc) | 588 | (Lisp_Object proc) |
| 553 | { | 589 | { |
| 554 | gnutls_session_t state; | 590 | return emacs_gnutls_deinit (proc); |
| 555 | |||
| 556 | CHECK_PROCESS (proc); | ||
| 557 | state = XPROCESS (proc)->gnutls_state; | ||
| 558 | |||
| 559 | if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT) | ||
| 560 | { | ||
| 561 | fn_gnutls_deinit (state); | ||
| 562 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1; | ||
| 563 | } | ||
| 564 | |||
| 565 | return Qt; | ||
| 566 | } | 591 | } |
| 567 | 592 | ||
| 568 | DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0, | 593 | DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0, |
| @@ -733,9 +758,6 @@ one trustfile (usually a CA bundle). */) | |||
| 733 | 758 | ||
| 734 | c_hostname = SSDATA (hostname); | 759 | c_hostname = SSDATA (hostname); |
| 735 | 760 | ||
| 736 | state = XPROCESS (proc)->gnutls_state; | ||
| 737 | XPROCESS (proc)->gnutls_p = 1; | ||
| 738 | |||
| 739 | if (NUMBERP (loglevel)) | 761 | if (NUMBERP (loglevel)) |
| 740 | { | 762 | { |
| 741 | fn_gnutls_global_set_log_function (gnutls_log_function); | 763 | fn_gnutls_global_set_log_function (gnutls_log_function); |
| @@ -749,40 +771,17 @@ one trustfile (usually a CA bundle). */) | |||
| 749 | if (! NILP (Fgnutls_errorp (global_init))) | 771 | if (! NILP (Fgnutls_errorp (global_init))) |
| 750 | return global_init; | 772 | return global_init; |
| 751 | 773 | ||
| 752 | /* deinit and free resources. */ | 774 | /* Before allocating new credentials, deallocate any credentials |
| 753 | if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_CRED_ALLOC) | 775 | that PROC might already have. */ |
| 754 | { | 776 | emacs_gnutls_deinit (proc); |
| 755 | GNUTLS_LOG (1, max_log_level, "deallocating credentials"); | ||
| 756 | |||
| 757 | if (EQ (type, Qgnutls_x509pki)) | ||
| 758 | { | ||
| 759 | GNUTLS_LOG (2, max_log_level, "deallocating x509 credentials"); | ||
| 760 | x509_cred = XPROCESS (proc)->gnutls_x509_cred; | ||
| 761 | fn_gnutls_certificate_free_credentials (x509_cred); | ||
| 762 | } | ||
| 763 | else if (EQ (type, Qgnutls_anon)) | ||
| 764 | { | ||
| 765 | GNUTLS_LOG (2, max_log_level, "deallocating anon credentials"); | ||
| 766 | anon_cred = XPROCESS (proc)->gnutls_anon_cred; | ||
| 767 | fn_gnutls_anon_free_client_credentials (anon_cred); | ||
| 768 | } | ||
| 769 | else | ||
| 770 | { | ||
| 771 | error ("unknown credential type"); | ||
| 772 | ret = GNUTLS_EMACS_ERROR_INVALID_TYPE; | ||
| 773 | } | ||
| 774 | |||
| 775 | if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT) | ||
| 776 | { | ||
| 777 | GNUTLS_LOG (1, max_log_level, "deallocating x509 credentials"); | ||
| 778 | Fgnutls_deinit (proc); | ||
| 779 | } | ||
| 780 | } | ||
| 781 | 777 | ||
| 778 | /* Mark PROC as a GnuTLS process. */ | ||
| 779 | XPROCESS (proc)->gnutls_p = 1; | ||
| 780 | XPROCESS (proc)->gnutls_x509_cred = NULL; | ||
| 781 | XPROCESS (proc)->gnutls_anon_cred = NULL; | ||
| 782 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY; | 782 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY; |
| 783 | 783 | ||
| 784 | GNUTLS_LOG (1, max_log_level, "allocating credentials"); | 784 | GNUTLS_LOG (1, max_log_level, "allocating credentials"); |
| 785 | |||
| 786 | if (EQ (type, Qgnutls_x509pki)) | 785 | if (EQ (type, Qgnutls_x509pki)) |
| 787 | { | 786 | { |
| 788 | GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); | 787 | GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); |
diff --git a/src/gnutls.h b/src/gnutls.h index e2a9bc9eaea..5ec6fb76c01 100644 --- a/src/gnutls.h +++ b/src/gnutls.h | |||
| @@ -60,6 +60,7 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, EMACS_INT nbyte); | |||
| 60 | 60 | ||
| 61 | extern int emacs_gnutls_record_check_pending (gnutls_session_t state); | 61 | extern int emacs_gnutls_record_check_pending (gnutls_session_t state); |
| 62 | extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); | 62 | extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); |
| 63 | extern Lisp_Object emacs_gnutls_deinit (Lisp_Object); | ||
| 63 | 64 | ||
| 64 | extern void syms_of_gnutls (void); | 65 | extern void syms_of_gnutls (void); |
| 65 | 66 | ||
diff --git a/src/process.c b/src/process.c index 90ad9c21681..3daa55b259e 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -642,6 +642,8 @@ make_process (Lisp_Object name) | |||
| 642 | p->gnutls_initstage = GNUTLS_STAGE_EMPTY; | 642 | p->gnutls_initstage = GNUTLS_STAGE_EMPTY; |
| 643 | p->gnutls_log_level = 0; | 643 | p->gnutls_log_level = 0; |
| 644 | p->gnutls_p = 0; | 644 | p->gnutls_p = 0; |
| 645 | p->gnutls_x509_cred = NULL; | ||
| 646 | p->gnutls_anon_cred = NULL; | ||
| 645 | #endif | 647 | #endif |
| 646 | 648 | ||
| 647 | /* If name is already in use, modify it until it is unused. */ | 649 | /* If name is already in use, modify it until it is unused. */ |
| @@ -3867,6 +3869,11 @@ deactivate_process (Lisp_Object proc) | |||
| 3867 | register int inchannel, outchannel; | 3869 | register int inchannel, outchannel; |
| 3868 | register struct Lisp_Process *p = XPROCESS (proc); | 3870 | register struct Lisp_Process *p = XPROCESS (proc); |
| 3869 | 3871 | ||
| 3872 | #ifdef HAVE_GNUTLS | ||
| 3873 | /* Delete GnuTLS structures in PROC, if any. */ | ||
| 3874 | emacs_gnutls_deinit (proc); | ||
| 3875 | #endif /* HAVE_GNUTLS */ | ||
| 3876 | |||
| 3870 | inchannel = p->infd; | 3877 | inchannel = p->infd; |
| 3871 | outchannel = p->outfd; | 3878 | outchannel = p->outfd; |
| 3872 | 3879 | ||