changeset 6817:cd47def2214a v7.4.730

patch 7.4.730 Problem: When setting the crypt key and using a swap file, text may be encrypted twice or unencrypted text remains in the swap file. (Issue 369) Solution: Call ml_preserve() before re-encrypting. Set correct index for next pointer block.
author Bram Moolenaar <bram@vim.org>
date Tue, 09 Jun 2015 18:35:25 +0200
parents ca3db36a6ed8
children 50b60e51a231
files src/memfile.c src/memline.c src/option.c src/proto/memline.pro src/version.c
diffstat 5 files changed, 48 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/memfile.c
+++ b/src/memfile.c
@@ -811,6 +811,8 @@ mf_rem_used(mfp, hp)
  *
  * Return the block header to the caller, including the memory block, so
  * it can be re-used. Make sure the page_count is right.
+ *
+ * Returns NULL if no block is released.
  */
     static bhdr_T *
 mf_release(mfp, page_count)
@@ -1219,7 +1221,7 @@ mf_trans_add(mfp, hp)
 }
 
 /*
- * Lookup a translation from the trans lists and delete the entry
+ * Lookup a translation from the trans lists and delete the entry.
  *
  * Return the positive new number when found, the old number when not found
  */
--- a/src/memline.c
+++ b/src/memline.c
@@ -488,7 +488,7 @@ ml_set_b0_crypt(buf, b0p)
 ml_set_crypt_key(buf, old_key, old_cm)
     buf_T	*buf;
     char_u	*old_key;
-    int		old_cm;
+    char_u	*old_cm;
 {
     memfile_T	*mfp = buf->b_ml.ml_mfp;
     bhdr_T	*hp;
@@ -500,15 +500,30 @@ ml_set_crypt_key(buf, old_key, old_cm)
     DATA_BL	*dp;
     blocknr_T	bnum;
     int		top;
+    int		old_method;
 
     if (mfp == NULL)
 	return;  /* no memfile yet, nothing to do */
+    old_method = crypt_method_nr_from_name(old_cm);
+
+    /* First make sure the swapfile is in a consistent state, using the old
+     * key and method. */
+    {
+	char_u *new_key = buf->b_p_key;
+	char_u *new_buf_cm = buf->b_p_cm;
+
+	buf->b_p_key = old_key;
+	buf->b_p_cm = old_cm;
+	ml_preserve(buf, FALSE);
+	buf->b_p_key = new_key;
+	buf->b_p_cm = new_buf_cm;
+    }
 
     /* Set the key, method and seed to be used for reading, these must be the
      * old values. */
     mfp->mf_old_key = old_key;
-    mfp->mf_old_cm = old_cm;
-    if (old_cm > 0)
+    mfp->mf_old_cm = old_method;
+    if (old_method > 0 && *old_key != NUL)
 	mch_memmove(mfp->mf_old_seed, mfp->mf_seed, MF_SEED_LEN);
 
     /* Update block 0 with the crypt flag and may set a new seed. */
@@ -561,8 +576,10 @@ ml_set_crypt_key(buf, old_key, old_cm)
 		    {
 			if (pp->pb_pointer[idx].pe_bnum < 0)
 			{
-			    /* Skip data block with negative block number. */
-			    ++idx;    /* get same block again for next index */
+			    /* Skip data block with negative block number.
+			     * Should not happen, because of the ml_preserve()
+			     * above. Get same block again for next index. */
+			    ++idx; 
 			    continue;
 			}
 
@@ -579,6 +596,7 @@ ml_set_crypt_key(buf, old_key, old_cm)
 
 			bnum = pp->pb_pointer[idx].pe_bnum;
 			page_count = pp->pb_pointer[idx].pe_page_count;
+			idx = 0;
 			continue;
 		    }
 		}
@@ -605,6 +623,8 @@ ml_set_crypt_key(buf, old_key, old_cm)
 	    idx = ip->ip_index + 1;	    /* go to next index */
 	    page_count = 1;
 	}
+	if (hp != NULL)
+	    mf_put(mfp, hp, FALSE, FALSE);  /* release previous block */
 
 	if (error > 0)
 	    EMSG(_("E843: Error while updating swap file crypt"));
@@ -4859,6 +4879,10 @@ ml_encrypt_data(mfp, data, offset, size)
     if (dp->db_id != DATA_ID)
 	return data;
 
+    state = ml_crypt_prepare(mfp, offset, FALSE);
+    if (state == NULL)
+	return data;
+
     new_data = (char_u *)alloc(size);
     if (new_data == NULL)
 	return NULL;
@@ -4870,7 +4894,6 @@ ml_encrypt_data(mfp, data, offset, size)
     mch_memmove(new_data, dp, head_end - (char_u *)dp);
 
     /* Encrypt the text. */
-    state = ml_crypt_prepare(mfp, offset, FALSE);
     crypt_encode(state, text_start, text_len, new_data + dp->db_txt_start);
     crypt_free_state(state);
 
@@ -4882,7 +4905,7 @@ ml_encrypt_data(mfp, data, offset, size)
 }
 
 /*
- * Decrypt the text in "data" if it points to a data block.
+ * Decrypt the text in "data" if it points to an encrypted data block.
  */
     void
 ml_decrypt_data(mfp, data, offset, size)
@@ -4907,10 +4930,13 @@ ml_decrypt_data(mfp, data, offset, size)
 						     || dp->db_txt_end > size)
 	    return;  /* data was messed up */
 
-	/* Decrypt the text in place. */
 	state = ml_crypt_prepare(mfp, offset, TRUE);
-	crypt_decode_inplace(state, text_start, text_len);
-	crypt_free_state(state);
+	if (state != NULL)
+	{
+	    /* Decrypt the text in place. */
+	    crypt_decode_inplace(state, text_start, text_len);
+	    crypt_free_state(state);
+	}
     }
 }
 
@@ -4943,6 +4969,8 @@ ml_crypt_prepare(mfp, offset, reading)
 	key = buf->b_p_key;
 	seed = mfp->mf_seed;
     }
+    if (*key == NUL)
+	return NULL;
 
     if (method_nr == CRYPT_M_ZIP)
     {
--- a/src/option.c
+++ b/src/option.c
@@ -6163,7 +6163,8 @@ did_set_string_option(opt_idx, varp, new
 # endif
 	if (STRCMP(curbuf->b_p_key, oldval) != 0)
 	    /* Need to update the swapfile. */
-	    ml_set_crypt_key(curbuf, oldval, crypt_get_method_nr(curbuf));
+	    ml_set_crypt_key(curbuf, oldval,
+			      *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
     }
 
     else if (gvarp == &p_cm)
@@ -6207,8 +6208,7 @@ did_set_string_option(opt_idx, varp, new
 	    else
 		p = curbuf->b_p_cm;
 	    if (STRCMP(s, p) != 0)
-		ml_set_crypt_key(curbuf, curbuf->b_p_key,
-						crypt_method_nr_from_name(s));
+		ml_set_crypt_key(curbuf, curbuf->b_p_key, s);
 
 	    /* If the global value changes need to update the swapfile for all
 	     * buffers using that value. */
@@ -6218,8 +6218,7 @@ did_set_string_option(opt_idx, varp, new
 
 		for (buf = firstbuf; buf != NULL; buf = buf->b_next)
 		    if (buf != curbuf && *buf->b_p_cm == NUL)
-			ml_set_crypt_key(buf, buf->b_p_key,
-					   crypt_method_nr_from_name(oldval));
+			ml_set_crypt_key(buf, buf->b_p_key, oldval);
 	    }
 	}
     }
--- a/src/proto/memline.pro
+++ b/src/proto/memline.pro
@@ -1,6 +1,6 @@
 /* memline.c */
 int ml_open __ARGS((buf_T *buf));
-void ml_set_crypt_key __ARGS((buf_T *buf, char_u *old_key, int old_cm));
+void ml_set_crypt_key __ARGS((buf_T *buf, char_u *old_key, char_u *old_cm));
 void ml_setname __ARGS((buf_T *buf));
 void ml_open_files __ARGS((void));
 void ml_open_file __ARGS((buf_T *buf));
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    730,
+/**/
     729,
 /**/
     728,