comparison src/undo.c @ 2223:81b83a19e127 vim73

More strict checks for the undo file.
author Bram Moolenaar <bram@vim.org>
date Wed, 26 May 2010 21:21:00 +0200
parents 271a5907f944
children d45902a5c61c
comparison
equal deleted inserted replaced
2222:271a5907f944 2223:81b83a19e127
105 static void u_freeentry __ARGS((u_entry_T *, long)); 105 static void u_freeentry __ARGS((u_entry_T *, long));
106 #ifdef FEAT_PERSISTENT_UNDO 106 #ifdef FEAT_PERSISTENT_UNDO
107 static void unserialize_pos __ARGS((pos_T *pos, FILE *fp)); 107 static void unserialize_pos __ARGS((pos_T *pos, FILE *fp));
108 static void unserialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp)); 108 static void unserialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp));
109 static char_u *u_get_undo_file_name __ARGS((char_u *, int reading)); 109 static char_u *u_get_undo_file_name __ARGS((char_u *, int reading));
110 static void u_free_uhp __ARGS((u_header_T *uhp));
110 static int serialize_uep __ARGS((u_entry_T *uep, FILE *fp)); 111 static int serialize_uep __ARGS((u_entry_T *uep, FILE *fp));
111 static void serialize_pos __ARGS((pos_T pos, FILE *fp)); 112 static void serialize_pos __ARGS((pos_T pos, FILE *fp));
112 static void serialize_visualinfo __ARGS((visualinfo_T info, FILE *fp)); 113 static void serialize_visualinfo __ARGS((visualinfo_T info, FILE *fp));
113 #endif 114 #endif
114 115
833 short old_idx = -1, new_idx = -1, cur_idx = -1; 834 short old_idx = -1, new_idx = -1, cur_idx = -1;
834 long num_read_uhps = 0; 835 long num_read_uhps = 0;
835 time_t seq_time; 836 time_t seq_time;
836 int i, j; 837 int i, j;
837 int c; 838 int c;
838 short found_first_uep = 0;
839 char_u **array; 839 char_u **array;
840 char_u *line; 840 char_u *line;
841 u_entry_T *uep, *last_uep, *nuep; 841 u_entry_T *uep, *last_uep;
842 u_header_T *uhp; 842 u_header_T *uhp;
843 u_header_T **uhp_table = NULL; 843 u_header_T **uhp_table = NULL;
844 char_u read_hash[UNDO_HASH_SIZE]; 844 char_u read_hash[UNDO_HASH_SIZE];
845 845
846 if (name == NULL) 846 if (name == NULL)
912 num_head = get4c(fp); 912 num_head = get4c(fp);
913 seq_last = get4c(fp); 913 seq_last = get4c(fp);
914 seq_cur = get4c(fp); 914 seq_cur = get4c(fp);
915 seq_time = get4c(fp); 915 seq_time = get4c(fp);
916 916
917 if (num_head < 0)
918 num_head = 0;
919
917 /* uhp_table will store the freshly created undo headers we allocate 920 /* uhp_table will store the freshly created undo headers we allocate
918 * until we insert them into curbuf. The table remains sorted by the 921 * until we insert them into curbuf. The table remains sorted by the
919 * sequence numbers of the headers. */ 922 * sequence numbers of the headers. */
920 uhp_table = (u_header_T **)U_ALLOC_LINE(num_head * sizeof(u_header_T *)); 923 uhp_table = (u_header_T **)U_ALLOC_LINE(num_head * sizeof(u_header_T *));
921 if (uhp_table == NULL) 924 if (uhp_table == NULL)
923 vim_memset(uhp_table, 0, num_head * sizeof(u_header_T *)); 926 vim_memset(uhp_table, 0, num_head * sizeof(u_header_T *));
924 927
925 c = get2c(fp); 928 c = get2c(fp);
926 while (c == UF_HEADER_MAGIC) 929 while (c == UF_HEADER_MAGIC)
927 { 930 {
928 found_first_uep = 0; 931 if (num_read_uhps >= num_head)
932 {
933 EMSG2(_("E831 Undo file corruption: num_head: %s"), file_name);
934 u_free_uhp(uhp);
935 goto error;
936 }
937
929 uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T)); 938 uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
930 if (uhp == NULL) 939 if (uhp == NULL)
931 goto error; 940 goto error;
932 vim_memset(uhp, 0, sizeof(u_header_T)); 941 vim_memset(uhp, 0, sizeof(u_header_T));
933 /* We're not actually trying to store pointers here. We're just storing 942 /* We're not actually trying to store pointers here. We're just storing
971 last_uep = NULL; 980 last_uep = NULL;
972 while ((uep_len = get4c(fp)) != -1) 981 while ((uep_len = get4c(fp)) != -1)
973 { 982 {
974 uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T)); 983 uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
975 if (uep == NULL) 984 if (uep == NULL)
985 {
986 u_free_uhp(uhp);
976 goto error; 987 goto error;
988 }
977 vim_memset(uep, 0, sizeof(u_entry_T)); 989 vim_memset(uep, 0, sizeof(u_entry_T));
990 if (last_uep == NULL)
991 uhp->uh_entry = uep;
992 else
993 last_uep->ue_next = uep;
994 last_uep = uep;
995
978 uep->ue_top = get4c(fp); 996 uep->ue_top = get4c(fp);
979 uep->ue_bot = get4c(fp); 997 uep->ue_bot = get4c(fp);
980 uep->ue_lcount = get4c(fp); 998 uep->ue_lcount = get4c(fp);
981 uep->ue_size = get4c(fp); 999 uep->ue_size = get4c(fp);
982 uep->ue_next = NULL; 1000 uep->ue_next = NULL;
983 array = (char_u **)U_ALLOC_LINE( 1001 array = (char_u **)U_ALLOC_LINE(
984 (unsigned)(sizeof(char_u *) * uep->ue_size)); 1002 (unsigned)(sizeof(char_u *) * uep->ue_size));
1003 if (array == NULL)
1004 {
1005 u_free_uhp(uhp);
1006 goto error;
1007 }
1008 vim_memset(array, 0, sizeof(char_u *) * uep->ue_size);
1009 uep->ue_array = array;
1010
985 for (i = 0; i < uep->ue_size; i++) 1011 for (i = 0; i < uep->ue_size; i++)
986 { 1012 {
987 line_len = get4c(fp); 1013 line_len = get4c(fp);
988 /* U_ALLOC_LINE provides an extra byte for the NUL terminator.*/ 1014 /* U_ALLOC_LINE provides an extra byte for the NUL terminator.*/
989 line = (char_u *)U_ALLOC_LINE( 1015 line = (char_u *)U_ALLOC_LINE(
990 (unsigned) (sizeof(char_u) * line_len)); 1016 (unsigned)(sizeof(char_u) * line_len));
991 if (line == NULL) 1017 if (line == NULL)
1018 {
1019 u_free_uhp(uhp);
992 goto error; 1020 goto error;
1021 }
993 for (j = 0; j < line_len; j++) 1022 for (j = 0; j < line_len; j++)
994 {
995 line[j] = getc(fp); 1023 line[j] = getc(fp);
996 }
997 line[j] = '\0'; 1024 line[j] = '\0';
998 array[i] = line; 1025 array[i] = line;
999 } 1026 }
1000 uep->ue_array = array;
1001 if (found_first_uep == 0)
1002 {
1003 uhp->uh_entry = uep;
1004 found_first_uep = 1;
1005 }
1006 else
1007 {
1008 last_uep->ue_next = uep;
1009 }
1010 last_uep = uep;
1011 } 1027 }
1012 1028
1013 /* Insertion sort the uhp into the table by its uh_seq. This is 1029 /* Insertion sort the uhp into the table by its uh_seq. This is
1014 * required because, while the number of uhps is limited to 1030 * required because, while the number of uhps is limited to
1015 * num_heads, and the uh_seq order is monotonic with respect to 1031 * num_head, and the uh_seq order is monotonic with respect to
1016 * creation time, the starting uh_seq can be > 0 if any undolevel 1032 * creation time, the starting uh_seq can be > 0 if any undolevel
1017 * culling was done at undofile write time, and there can be uh_seq 1033 * culling was done at undofile write time, and there can be uh_seq
1018 * gaps in the uhps. 1034 * gaps in the uhps.
1019 */ 1035 */
1020 for (i = num_read_uhps - 1; i >= -1; i--) 1036 for (i = num_read_uhps - 1; i >= -1; i--)
1026 /* If we've had to move from the rightmost side of the table, 1042 /* If we've had to move from the rightmost side of the table,
1027 * we have to shift everything to the right by one spot. */ 1043 * we have to shift everything to the right by one spot. */
1028 if (num_read_uhps - i - 1 > 0) 1044 if (num_read_uhps - i - 1 > 0)
1029 { 1045 {
1030 memmove(uhp_table + i + 2, uhp_table + i + 1, 1046 memmove(uhp_table + i + 2, uhp_table + i + 1,
1031 (num_read_uhps - i - 1) * sizeof(u_header_T *)); 1047 (num_read_uhps - i - 1) * sizeof(u_header_T *));
1032 } 1048 }
1033 uhp_table[i + 1] = uhp; 1049 uhp_table[i + 1] = uhp;
1034 break; 1050 break;
1035 } 1051 }
1036 else if (uhp->uh_seq == uhp_table[i]->uh_seq) 1052 else if (uhp->uh_seq == uhp_table[i]->uh_seq)
1037 { 1053 {
1038 EMSG2(_("E826 Undo file corruption: duplicate uh_seq: %s"), 1054 EMSG2(_("E826 Undo file corruption: duplicate uh_seq: %s"),
1039 file_name); 1055 file_name);
1056 u_free_uhp(uhp);
1040 goto error; 1057 goto error;
1041 } 1058 }
1042 } 1059 }
1043 num_read_uhps++; 1060 num_read_uhps++;
1044 c = get2c(fp); 1061 c = get2c(fp);
1103 if (line_ptr != NULL) 1120 if (line_ptr != NULL)
1104 U_FREE_LINE(line_ptr); 1121 U_FREE_LINE(line_ptr);
1105 if (uhp_table != NULL) 1122 if (uhp_table != NULL)
1106 { 1123 {
1107 for (i = 0; i < num_head; i++) 1124 for (i = 0; i < num_head; i++)
1108 {
1109 if (uhp_table[i] != NULL) 1125 if (uhp_table[i] != NULL)
1110 { 1126 u_free_uhp(uhp_table[i]);
1111 uep = uhp_table[i]->uh_entry;
1112 while (uep != NULL)
1113 {
1114 nuep = uep->ue_next;
1115 u_freeentry(uep, uep->ue_size);
1116 uep = nuep;
1117 }
1118 U_FREE_LINE(uhp_table[i]);
1119 }
1120 }
1121 U_FREE_LINE(uhp_table); 1127 U_FREE_LINE(uhp_table);
1122 } 1128 }
1123 1129
1124 theend: 1130 theend:
1125 if (fp != NULL) 1131 if (fp != NULL)
1126 fclose(fp); 1132 fclose(fp);
1127 if (file_name != name) 1133 if (file_name != name)
1128 vim_free(file_name); 1134 vim_free(file_name);
1129 return; 1135 return;
1136 }
1137
1138 static void
1139 u_free_uhp(uhp)
1140 u_header_T *uhp;
1141 {
1142 u_entry_T *nuep;
1143 u_entry_T *uep;
1144
1145 uep = uhp->uh_entry;
1146 while (uep != NULL)
1147 {
1148 nuep = uep->ue_next;
1149 u_freeentry(uep, uep->ue_size);
1150 uep = nuep;
1151 }
1152 U_FREE_LINE(uhp);
1130 } 1153 }
1131 1154
1132 /* 1155 /*
1133 * Serialize "uep" to "fp". 1156 * Serialize "uep" to "fp".
1134 */ 1157 */