Mercurial > vim
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 */ |