Fossil SCM

Improvements to the control-file parser. Not recognizes the T-line for tags.

drh 2007-09-21 19:18 trunk
Commit 3dc92fdb7f45b8a6fe22430bd260a943a72ee4dd
1 file changed +246 -101
+246 -101
--- src/manifest.c
+++ src/manifest.c
@@ -47,10 +47,16 @@
4747
int nParentAlloc; /* Slots allocated in azParent[] */
4848
char **azParent; /* UUIDs of parents */
4949
int nCChild; /* Number of cluster children */
5050
int nCChildAlloc; /* Number of closts allocated in azCChild[] */
5151
char **azCChild; /* UUIDs of referenced objects in a cluster */
52
+ int nTag; /* Number of T lines */
53
+ int nTagAlloc; /* Slots allocated in aTag[] */
54
+ struct {
55
+ char *zName; /* Name of the tag */
56
+ char *zUuid; /* UUID that the tag is applied to */
57
+ } *aTag;
5258
};
5359
#endif
5460
5561
5662
/*
@@ -80,19 +86,21 @@
8086
*/
8187
int manifest_parse(Manifest *p, Blob *pContent){
8288
int seenHeader = 0;
8389
int i;
8490
Blob line, token, a1, a2, a3;
91
+ char zPrevLine[10];
8592
8693
memset(p, 0, sizeof(*p));
8794
memcpy(&p->content, pContent, sizeof(p->content));
8895
blob_zero(pContent);
8996
pContent = &p->content;
9097
9198
blob_zero(&a1);
9299
blob_zero(&a2);
93100
md5sum_init();
101
+ zPrevLine[0] = 0;
94102
while( blob_line(pContent, &line) ){
95103
char *z = blob_buffer(&line);
96104
if( z[0]=='-' ){
97105
if( strncmp(z, "-----BEGIN PGP ", 15)!=0 ){
98106
goto manifest_syntax_error;
@@ -102,116 +110,253 @@
102110
}
103111
while( blob_line(pContent, &line)>2 ){}
104112
if( blob_line(pContent, &line)==0 ) break;
105113
z = blob_buffer(&line);
106114
}
115
+ if( strcmp(z, zPrevLine)<0 ){
116
+ /* Lines of a manifest must occur in lexicographical order */
117
+ goto manifest_syntax_error;
118
+ }
119
+ sqlite3_snprintf(sizeof(zPrevLine), zPrevLine, "%s", z);
107120
seenHeader = 1;
108121
if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
109
- if( z[0]=='F' ){
110
- char *zName, *zUuid;
111
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
112
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
113
- if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
114
- if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
115
- zName = blob_terminate(&a1);
116
- zUuid = blob_terminate(&a2);
117
- if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
118
- if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
119
- defossilize(zName);
120
- if( !file_is_simple_pathname(zName) ){
121
- goto manifest_syntax_error;
122
- }
123
- if( p->nFile>=p->nFileAlloc ){
124
- p->nFileAlloc = p->nFileAlloc*2 + 10;
125
- p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
126
- if( p->aFile==0 ) fossil_panic("out of memory");
127
- }
128
- i = p->nFile++;
129
- p->aFile[i].zName = zName;
130
- p->aFile[i].zUuid = zUuid;
131
- if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
132
- goto manifest_syntax_error;
133
- }
134
- }else if( z[0]=='C' ){
135
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
136
- if( p->zComment!=0 ) goto manifest_syntax_error;
137
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
138
- if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
139
- p->zComment = blob_terminate(&a1);
140
- defossilize(p->zComment);
141
- }else if( z[0]=='D' ){
142
- char *zDate;
143
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
144
- if( p->rDate!=0.0 ) goto manifest_syntax_error;
145
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
146
- if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
147
- zDate = blob_terminate(&a1);
148
- p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
149
- }else if( z[0]=='M' ){
150
- char *zUuid;
151
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
152
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
153
- zUuid = blob_terminate(&a1);
154
- if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
155
- if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
156
- if( p->nCChild>=p->nCChildAlloc ){
157
- p->nCChildAlloc = p->nCChildAlloc*2 + 10;
158
- p->azCChild =
159
- realloc(p->azCChild, p->nCChildAlloc*sizeof(p->azCChild[0]) );
160
- if( p->azCChild==0 ) fossil_panic("out of memory");
161
- }
162
- i = p->nCChild++;
163
- p->azCChild[i] = zUuid;
164
- if( i>0 && strcmp(p->azCChild[i-1], zUuid)>=0 ){
165
- goto manifest_syntax_error;
166
- }
167
- }else if( z[0]=='U' ){
168
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
169
- if( p->zUser!=0 ) goto manifest_syntax_error;
170
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
171
- if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
172
- p->zUser = blob_terminate(&a1);
173
- defossilize(p->zUser);
174
- }else if( z[0]=='R' ){
175
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
176
- if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
177
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
178
- if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
179
- if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
180
- p->zRepoCksum = blob_terminate(&a1);
181
- if( !validate16(p->zRepoCksum, 32) ) goto manifest_syntax_error;
182
- }else if( z[0]=='P' ){
183
- md5sum_step_text(blob_buffer(&line), blob_size(&line));
184
- while( blob_token(&line, &a1) ){
185
- char *zUuid;
186
- if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
187
- zUuid = blob_terminate(&a1);
188
- if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
189
- if( p->nParent>=p->nParentAlloc ){
190
- p->nParentAlloc = p->nParentAlloc*2 + 5;
191
- p->azParent = realloc(p->azParent, p->nParentAlloc*sizeof(char*));
192
- if( p->azParent==0 ) fossil_panic("out of memory");
193
- }
194
- i = p->nParent++;
195
- p->azParent[i] = zUuid;
196
- }
197
- }else if( z[0]=='Z' ){
198
- int rc;
199
- Blob hash;
200
- if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
201
- if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
202
- if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
203
- if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
204
- md5sum_finish(&hash);
205
- rc = blob_compare(&hash, &a1);
206
- blob_reset(&hash);
207
- if( rc!=0 ) goto manifest_syntax_error;
208
- }else{
209
- goto manifest_syntax_error;
122
+ switch( z[0] ){
123
+ /*
124
+ ** C <comment>
125
+ **
126
+ ** Comment text is fossil-encoded. There may be no more than
127
+ ** one C line. C lines are required for manifests and are
128
+ ** disallowed on all other control files.
129
+ */
130
+ case 'C': {
131
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
132
+ if( p->zComment!=0 ) goto manifest_syntax_error;
133
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
134
+ if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
135
+ p->zComment = blob_terminate(&a1);
136
+ defossilize(p->zComment);
137
+ break;
138
+ }
139
+
140
+ /*
141
+ ** D <timestamp>
142
+ **
143
+ ** The timestamp should be ISO 8601. YYYY-MM-DDtHH:MM:SS
144
+ ** There can be no more than 1 D line. D lines are required
145
+ ** for all control files except for clusters.
146
+ */
147
+ case 'D': {
148
+ char *zDate;
149
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
150
+ if( p->rDate!=0.0 ) goto manifest_syntax_error;
151
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
152
+ if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
153
+ zDate = blob_terminate(&a1);
154
+ p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
155
+ break;
156
+ }
157
+
158
+ /*
159
+ ** F <filename> <uuid>
160
+ **
161
+ ** Identifies a file in a manifest. Multiple F lines are
162
+ ** allowed in a manifest. F lines are not allowed in any
163
+ ** other control file. The filename is fossil-encoded.
164
+ */
165
+ case 'F': {
166
+ char *zName, *zUuid;
167
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
168
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
169
+ if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
170
+ if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
171
+ zName = blob_terminate(&a1);
172
+ zUuid = blob_terminate(&a2);
173
+ if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
174
+ if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
175
+ defossilize(zName);
176
+ if( !file_is_simple_pathname(zName) ){
177
+ goto manifest_syntax_error;
178
+ }
179
+ if( p->nFile>=p->nFileAlloc ){
180
+ p->nFileAlloc = p->nFileAlloc*2 + 10;
181
+ p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
182
+ if( p->aFile==0 ) fossil_panic("out of memory");
183
+ }
184
+ i = p->nFile++;
185
+ p->aFile[i].zName = zName;
186
+ p->aFile[i].zUuid = zUuid;
187
+ if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
188
+ goto manifest_syntax_error;
189
+ }
190
+ break;
191
+ }
192
+
193
+ /*
194
+ ** M <uuid>
195
+ **
196
+ ** An M-line identifies another artifact by its UUID. M-lines
197
+ ** occur in clusters only.
198
+ */
199
+ case 'M': {
200
+ char *zUuid;
201
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
202
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
203
+ zUuid = blob_terminate(&a1);
204
+ if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
205
+ if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
206
+ if( p->nCChild>=p->nCChildAlloc ){
207
+ p->nCChildAlloc = p->nCChildAlloc*2 + 10;
208
+ p->azCChild =
209
+ realloc(p->azCChild, p->nCChildAlloc*sizeof(p->azCChild[0]) );
210
+ if( p->azCChild==0 ) fossil_panic("out of memory");
211
+ }
212
+ i = p->nCChild++;
213
+ p->azCChild[i] = zUuid;
214
+ if( i>0 && strcmp(p->azCChild[i-1], zUuid)>=0 ){
215
+ goto manifest_syntax_error;
216
+ }
217
+ break;
218
+ }
219
+
220
+ /*
221
+ ** T (+|-)<tagname> <uuid>
222
+ **
223
+ ** Create or cancel a tag. The tagname is fossil-encoded. The
224
+ ** first character must be either "+" to create or "-" to delete.
225
+ ** Tags are not allowed in clusters. Multiple T lines are allowed.
226
+ */
227
+ case 'T': {
228
+ char *zName, *zUuid;
229
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
230
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
231
+ if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
232
+ if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
233
+ zName = blob_terminate(&a1);
234
+ zUuid = blob_terminate(&a2);
235
+ if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
236
+ if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
237
+ defossilize(zName);
238
+ if( zName[0]!='-' && zName[0]!='+' ){
239
+ goto manifest_syntax_error;
240
+ }
241
+ if( p->nTag>=p->nTagAlloc ){
242
+ p->nTagAlloc = p->nTagAlloc*2 + 10;
243
+ p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
244
+ if( p->aTag==0 ) fossil_panic("out of memory");
245
+ }
246
+ i = p->nTag++;
247
+ p->aTag[i].zName = zName;
248
+ p->aTag[i].zUuid = zUuid;
249
+ if( i>0 && strcmp(p->aTag[i-1].zName, zName)>=0 ){
250
+ goto manifest_syntax_error;
251
+ }
252
+ break;
253
+ }
254
+
255
+ /*
256
+ ** U <login>
257
+ **
258
+ ** Identify the user who created this control file by their
259
+ ** login. Only one U line is allowed. Prohibited in clusters.
260
+ */
261
+ case 'U': {
262
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
263
+ if( p->zUser!=0 ) goto manifest_syntax_error;
264
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
265
+ if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
266
+ p->zUser = blob_terminate(&a1);
267
+ defossilize(p->zUser);
268
+ break;
269
+ }
270
+
271
+ /*
272
+ ** R <md5sum>
273
+ **
274
+ ** Specify the MD5 checksum of the entire baseline in a
275
+ ** manifest.
276
+ */
277
+ case 'R': {
278
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
279
+ if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
280
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
281
+ if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
282
+ if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
283
+ p->zRepoCksum = blob_terminate(&a1);
284
+ if( !validate16(p->zRepoCksum, 32) ) goto manifest_syntax_error;
285
+ break;
286
+ }
287
+
288
+ /*
289
+ ** P <uuid> ...
290
+ **
291
+ ** Specify one or more other artifacts where are the parents of
292
+ ** this artifact. The first parent is the primary parent. All
293
+ ** others are parents by merge.
294
+ */
295
+ case 'P': {
296
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
297
+ while( blob_token(&line, &a1) ){
298
+ char *zUuid;
299
+ if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
300
+ zUuid = blob_terminate(&a1);
301
+ if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
302
+ if( p->nParent>=p->nParentAlloc ){
303
+ p->nParentAlloc = p->nParentAlloc*2 + 5;
304
+ p->azParent = realloc(p->azParent, p->nParentAlloc*sizeof(char*));
305
+ if( p->azParent==0 ) fossil_panic("out of memory");
306
+ }
307
+ i = p->nParent++;
308
+ p->azParent[i] = zUuid;
309
+ }
310
+ break;
311
+ }
312
+
313
+ /*
314
+ ** Z <md5sum>
315
+ **
316
+ ** MD5 checksum on this control file. The checksum is over all
317
+ ** lines (other than PGP-signature lines) prior to the current
318
+ ** line. This must be the last record.
319
+ */
320
+ case 'Z': {
321
+ int rc;
322
+ Blob hash;
323
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
324
+ if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
325
+ if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
326
+ if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
327
+ md5sum_finish(&hash);
328
+ rc = blob_compare(&hash, &a1);
329
+ blob_reset(&hash);
330
+ if( rc!=0 ) goto manifest_syntax_error;
331
+ break;
332
+ }
333
+ default: {
334
+ goto manifest_syntax_error;
335
+ }
210336
}
211337
}
212338
if( !seenHeader ) goto manifest_syntax_error;
339
+
340
+ if( p->nFile>0 ){
341
+ if( p->nCChild>0 ) goto manifest_syntax_error;
342
+ if( p->rDate==0.0 ) goto manifest_syntax_error;
343
+ }else if( p->nCChild>0 ){
344
+ if( p->rDate>0.0 ) goto manifest_syntax_error;
345
+ if( p->zComment!=0 ) goto manifest_syntax_error;
346
+ if( p->zUser!=0 ) goto manifest_syntax_error;
347
+ if( p->nTag>0 ) goto manifest_syntax_error;
348
+ if( p->nParent>0 ) goto manifest_syntax_error;
349
+ if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
350
+ }else if( p->nTag>0 ){
351
+ if( p->rDate<=0.0 ) goto manifest_syntax_error;
352
+ if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
353
+ if( p->nParent>0 ) goto manifest_syntax_error;
354
+ }else{
355
+ goto manifest_syntax_error;
356
+ }
357
+
213358
md5sum_init();
214359
return 1;
215360
216361
manifest_syntax_error:
217362
md5sum_init();
218363
--- src/manifest.c
+++ src/manifest.c
@@ -47,10 +47,16 @@
47 int nParentAlloc; /* Slots allocated in azParent[] */
48 char **azParent; /* UUIDs of parents */
49 int nCChild; /* Number of cluster children */
50 int nCChildAlloc; /* Number of closts allocated in azCChild[] */
51 char **azCChild; /* UUIDs of referenced objects in a cluster */
 
 
 
 
 
 
52 };
53 #endif
54
55
56 /*
@@ -80,19 +86,21 @@
80 */
81 int manifest_parse(Manifest *p, Blob *pContent){
82 int seenHeader = 0;
83 int i;
84 Blob line, token, a1, a2, a3;
 
85
86 memset(p, 0, sizeof(*p));
87 memcpy(&p->content, pContent, sizeof(p->content));
88 blob_zero(pContent);
89 pContent = &p->content;
90
91 blob_zero(&a1);
92 blob_zero(&a2);
93 md5sum_init();
 
94 while( blob_line(pContent, &line) ){
95 char *z = blob_buffer(&line);
96 if( z[0]=='-' ){
97 if( strncmp(z, "-----BEGIN PGP ", 15)!=0 ){
98 goto manifest_syntax_error;
@@ -102,116 +110,253 @@
102 }
103 while( blob_line(pContent, &line)>2 ){}
104 if( blob_line(pContent, &line)==0 ) break;
105 z = blob_buffer(&line);
106 }
 
 
 
 
 
107 seenHeader = 1;
108 if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
109 if( z[0]=='F' ){
110 char *zName, *zUuid;
111 md5sum_step_text(blob_buffer(&line), blob_size(&line));
112 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
113 if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
114 if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
115 zName = blob_terminate(&a1);
116 zUuid = blob_terminate(&a2);
117 if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
118 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
119 defossilize(zName);
120 if( !file_is_simple_pathname(zName) ){
121 goto manifest_syntax_error;
122 }
123 if( p->nFile>=p->nFileAlloc ){
124 p->nFileAlloc = p->nFileAlloc*2 + 10;
125 p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
126 if( p->aFile==0 ) fossil_panic("out of memory");
127 }
128 i = p->nFile++;
129 p->aFile[i].zName = zName;
130 p->aFile[i].zUuid = zUuid;
131 if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
132 goto manifest_syntax_error;
133 }
134 }else if( z[0]=='C' ){
135 md5sum_step_text(blob_buffer(&line), blob_size(&line));
136 if( p->zComment!=0 ) goto manifest_syntax_error;
137 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
138 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
139 p->zComment = blob_terminate(&a1);
140 defossilize(p->zComment);
141 }else if( z[0]=='D' ){
142 char *zDate;
143 md5sum_step_text(blob_buffer(&line), blob_size(&line));
144 if( p->rDate!=0.0 ) goto manifest_syntax_error;
145 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
146 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
147 zDate = blob_terminate(&a1);
148 p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
149 }else if( z[0]=='M' ){
150 char *zUuid;
151 md5sum_step_text(blob_buffer(&line), blob_size(&line));
152 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
153 zUuid = blob_terminate(&a1);
154 if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
155 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
156 if( p->nCChild>=p->nCChildAlloc ){
157 p->nCChildAlloc = p->nCChildAlloc*2 + 10;
158 p->azCChild =
159 realloc(p->azCChild, p->nCChildAlloc*sizeof(p->azCChild[0]) );
160 if( p->azCChild==0 ) fossil_panic("out of memory");
161 }
162 i = p->nCChild++;
163 p->azCChild[i] = zUuid;
164 if( i>0 && strcmp(p->azCChild[i-1], zUuid)>=0 ){
165 goto manifest_syntax_error;
166 }
167 }else if( z[0]=='U' ){
168 md5sum_step_text(blob_buffer(&line), blob_size(&line));
169 if( p->zUser!=0 ) goto manifest_syntax_error;
170 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
171 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
172 p->zUser = blob_terminate(&a1);
173 defossilize(p->zUser);
174 }else if( z[0]=='R' ){
175 md5sum_step_text(blob_buffer(&line), blob_size(&line));
176 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
177 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
178 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
179 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
180 p->zRepoCksum = blob_terminate(&a1);
181 if( !validate16(p->zRepoCksum, 32) ) goto manifest_syntax_error;
182 }else if( z[0]=='P' ){
183 md5sum_step_text(blob_buffer(&line), blob_size(&line));
184 while( blob_token(&line, &a1) ){
185 char *zUuid;
186 if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
187 zUuid = blob_terminate(&a1);
188 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
189 if( p->nParent>=p->nParentAlloc ){
190 p->nParentAlloc = p->nParentAlloc*2 + 5;
191 p->azParent = realloc(p->azParent, p->nParentAlloc*sizeof(char*));
192 if( p->azParent==0 ) fossil_panic("out of memory");
193 }
194 i = p->nParent++;
195 p->azParent[i] = zUuid;
196 }
197 }else if( z[0]=='Z' ){
198 int rc;
199 Blob hash;
200 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
201 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
202 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
203 if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
204 md5sum_finish(&hash);
205 rc = blob_compare(&hash, &a1);
206 blob_reset(&hash);
207 if( rc!=0 ) goto manifest_syntax_error;
208 }else{
209 goto manifest_syntax_error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210 }
211 }
212 if( !seenHeader ) goto manifest_syntax_error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213 md5sum_init();
214 return 1;
215
216 manifest_syntax_error:
217 md5sum_init();
218
--- src/manifest.c
+++ src/manifest.c
@@ -47,10 +47,16 @@
47 int nParentAlloc; /* Slots allocated in azParent[] */
48 char **azParent; /* UUIDs of parents */
49 int nCChild; /* Number of cluster children */
50 int nCChildAlloc; /* Number of closts allocated in azCChild[] */
51 char **azCChild; /* UUIDs of referenced objects in a cluster */
52 int nTag; /* Number of T lines */
53 int nTagAlloc; /* Slots allocated in aTag[] */
54 struct {
55 char *zName; /* Name of the tag */
56 char *zUuid; /* UUID that the tag is applied to */
57 } *aTag;
58 };
59 #endif
60
61
62 /*
@@ -80,19 +86,21 @@
86 */
87 int manifest_parse(Manifest *p, Blob *pContent){
88 int seenHeader = 0;
89 int i;
90 Blob line, token, a1, a2, a3;
91 char zPrevLine[10];
92
93 memset(p, 0, sizeof(*p));
94 memcpy(&p->content, pContent, sizeof(p->content));
95 blob_zero(pContent);
96 pContent = &p->content;
97
98 blob_zero(&a1);
99 blob_zero(&a2);
100 md5sum_init();
101 zPrevLine[0] = 0;
102 while( blob_line(pContent, &line) ){
103 char *z = blob_buffer(&line);
104 if( z[0]=='-' ){
105 if( strncmp(z, "-----BEGIN PGP ", 15)!=0 ){
106 goto manifest_syntax_error;
@@ -102,116 +110,253 @@
110 }
111 while( blob_line(pContent, &line)>2 ){}
112 if( blob_line(pContent, &line)==0 ) break;
113 z = blob_buffer(&line);
114 }
115 if( strcmp(z, zPrevLine)<0 ){
116 /* Lines of a manifest must occur in lexicographical order */
117 goto manifest_syntax_error;
118 }
119 sqlite3_snprintf(sizeof(zPrevLine), zPrevLine, "%s", z);
120 seenHeader = 1;
121 if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
122 switch( z[0] ){
123 /*
124 ** C <comment>
125 **
126 ** Comment text is fossil-encoded. There may be no more than
127 ** one C line. C lines are required for manifests and are
128 ** disallowed on all other control files.
129 */
130 case 'C': {
131 md5sum_step_text(blob_buffer(&line), blob_size(&line));
132 if( p->zComment!=0 ) goto manifest_syntax_error;
133 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
134 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
135 p->zComment = blob_terminate(&a1);
136 defossilize(p->zComment);
137 break;
138 }
139
140 /*
141 ** D <timestamp>
142 **
143 ** The timestamp should be ISO 8601. YYYY-MM-DDtHH:MM:SS
144 ** There can be no more than 1 D line. D lines are required
145 ** for all control files except for clusters.
146 */
147 case 'D': {
148 char *zDate;
149 md5sum_step_text(blob_buffer(&line), blob_size(&line));
150 if( p->rDate!=0.0 ) goto manifest_syntax_error;
151 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
152 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
153 zDate = blob_terminate(&a1);
154 p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
155 break;
156 }
157
158 /*
159 ** F <filename> <uuid>
160 **
161 ** Identifies a file in a manifest. Multiple F lines are
162 ** allowed in a manifest. F lines are not allowed in any
163 ** other control file. The filename is fossil-encoded.
164 */
165 case 'F': {
166 char *zName, *zUuid;
167 md5sum_step_text(blob_buffer(&line), blob_size(&line));
168 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
169 if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
170 if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
171 zName = blob_terminate(&a1);
172 zUuid = blob_terminate(&a2);
173 if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
174 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
175 defossilize(zName);
176 if( !file_is_simple_pathname(zName) ){
177 goto manifest_syntax_error;
178 }
179 if( p->nFile>=p->nFileAlloc ){
180 p->nFileAlloc = p->nFileAlloc*2 + 10;
181 p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
182 if( p->aFile==0 ) fossil_panic("out of memory");
183 }
184 i = p->nFile++;
185 p->aFile[i].zName = zName;
186 p->aFile[i].zUuid = zUuid;
187 if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
188 goto manifest_syntax_error;
189 }
190 break;
191 }
192
193 /*
194 ** M <uuid>
195 **
196 ** An M-line identifies another artifact by its UUID. M-lines
197 ** occur in clusters only.
198 */
199 case 'M': {
200 char *zUuid;
201 md5sum_step_text(blob_buffer(&line), blob_size(&line));
202 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
203 zUuid = blob_terminate(&a1);
204 if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
205 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
206 if( p->nCChild>=p->nCChildAlloc ){
207 p->nCChildAlloc = p->nCChildAlloc*2 + 10;
208 p->azCChild =
209 realloc(p->azCChild, p->nCChildAlloc*sizeof(p->azCChild[0]) );
210 if( p->azCChild==0 ) fossil_panic("out of memory");
211 }
212 i = p->nCChild++;
213 p->azCChild[i] = zUuid;
214 if( i>0 && strcmp(p->azCChild[i-1], zUuid)>=0 ){
215 goto manifest_syntax_error;
216 }
217 break;
218 }
219
220 /*
221 ** T (+|-)<tagname> <uuid>
222 **
223 ** Create or cancel a tag. The tagname is fossil-encoded. The
224 ** first character must be either "+" to create or "-" to delete.
225 ** Tags are not allowed in clusters. Multiple T lines are allowed.
226 */
227 case 'T': {
228 char *zName, *zUuid;
229 md5sum_step_text(blob_buffer(&line), blob_size(&line));
230 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
231 if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
232 if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
233 zName = blob_terminate(&a1);
234 zUuid = blob_terminate(&a2);
235 if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
236 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
237 defossilize(zName);
238 if( zName[0]!='-' && zName[0]!='+' ){
239 goto manifest_syntax_error;
240 }
241 if( p->nTag>=p->nTagAlloc ){
242 p->nTagAlloc = p->nTagAlloc*2 + 10;
243 p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
244 if( p->aTag==0 ) fossil_panic("out of memory");
245 }
246 i = p->nTag++;
247 p->aTag[i].zName = zName;
248 p->aTag[i].zUuid = zUuid;
249 if( i>0 && strcmp(p->aTag[i-1].zName, zName)>=0 ){
250 goto manifest_syntax_error;
251 }
252 break;
253 }
254
255 /*
256 ** U <login>
257 **
258 ** Identify the user who created this control file by their
259 ** login. Only one U line is allowed. Prohibited in clusters.
260 */
261 case 'U': {
262 md5sum_step_text(blob_buffer(&line), blob_size(&line));
263 if( p->zUser!=0 ) goto manifest_syntax_error;
264 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
265 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
266 p->zUser = blob_terminate(&a1);
267 defossilize(p->zUser);
268 break;
269 }
270
271 /*
272 ** R <md5sum>
273 **
274 ** Specify the MD5 checksum of the entire baseline in a
275 ** manifest.
276 */
277 case 'R': {
278 md5sum_step_text(blob_buffer(&line), blob_size(&line));
279 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
280 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
281 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
282 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
283 p->zRepoCksum = blob_terminate(&a1);
284 if( !validate16(p->zRepoCksum, 32) ) goto manifest_syntax_error;
285 break;
286 }
287
288 /*
289 ** P <uuid> ...
290 **
291 ** Specify one or more other artifacts where are the parents of
292 ** this artifact. The first parent is the primary parent. All
293 ** others are parents by merge.
294 */
295 case 'P': {
296 md5sum_step_text(blob_buffer(&line), blob_size(&line));
297 while( blob_token(&line, &a1) ){
298 char *zUuid;
299 if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
300 zUuid = blob_terminate(&a1);
301 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
302 if( p->nParent>=p->nParentAlloc ){
303 p->nParentAlloc = p->nParentAlloc*2 + 5;
304 p->azParent = realloc(p->azParent, p->nParentAlloc*sizeof(char*));
305 if( p->azParent==0 ) fossil_panic("out of memory");
306 }
307 i = p->nParent++;
308 p->azParent[i] = zUuid;
309 }
310 break;
311 }
312
313 /*
314 ** Z <md5sum>
315 **
316 ** MD5 checksum on this control file. The checksum is over all
317 ** lines (other than PGP-signature lines) prior to the current
318 ** line. This must be the last record.
319 */
320 case 'Z': {
321 int rc;
322 Blob hash;
323 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
324 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
325 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
326 if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
327 md5sum_finish(&hash);
328 rc = blob_compare(&hash, &a1);
329 blob_reset(&hash);
330 if( rc!=0 ) goto manifest_syntax_error;
331 break;
332 }
333 default: {
334 goto manifest_syntax_error;
335 }
336 }
337 }
338 if( !seenHeader ) goto manifest_syntax_error;
339
340 if( p->nFile>0 ){
341 if( p->nCChild>0 ) goto manifest_syntax_error;
342 if( p->rDate==0.0 ) goto manifest_syntax_error;
343 }else if( p->nCChild>0 ){
344 if( p->rDate>0.0 ) goto manifest_syntax_error;
345 if( p->zComment!=0 ) goto manifest_syntax_error;
346 if( p->zUser!=0 ) goto manifest_syntax_error;
347 if( p->nTag>0 ) goto manifest_syntax_error;
348 if( p->nParent>0 ) goto manifest_syntax_error;
349 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
350 }else if( p->nTag>0 ){
351 if( p->rDate<=0.0 ) goto manifest_syntax_error;
352 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
353 if( p->nParent>0 ) goto manifest_syntax_error;
354 }else{
355 goto manifest_syntax_error;
356 }
357
358 md5sum_init();
359 return 1;
360
361 manifest_syntax_error:
362 md5sum_init();
363

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button