Add zip_buffer_t, memory buffer with bounds checked access.
Use for parsing and assembling data structures.
diff --git a/lib/zip_extra_field.c b/lib/zip_extra_field.c
index 482703e..452c296 100644
--- a/lib/zip_extra_field.c
+++ b/lib/zip_extra_field.c
@@ -210,29 +210,31 @@
 zip_extra_field_t *
 _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_error_t *error)
 {
+    zip_buffer_t *buffer;
     zip_extra_field_t *ef, *ef2, *ef_head;
-    const zip_uint8_t *p;
-    zip_uint16_t fid, flen;
 
+    if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
+        return NULL;
+    }
+    
     ef_head = ef = NULL;
-    for (p=data; p<data+len; p+=flen) {
-	if (p+4 > data+len) {
-	    zip_error_set(error, ZIP_ER_INCONS, 0);
-	    _zip_ef_free(ef_head);
-	    return NULL;
-	}
+    
+    while (_zip_buffer_ok(buffer) && !_zip_buffer_eof(buffer)) {
+        zip_uint16_t fid, flen;
+        zip_uint8_t *ef_data;
+        
+        fid = _zip_buffer_get_16(buffer);
+	flen = _zip_buffer_get_16(buffer);
+        ef_data = _zip_buffer_get(buffer, flen);
 
-	fid = _zip_get_16(&p);
-	flen = _zip_get_16(&p);
-
-	if (p+flen > data+len) {
-	    zip_error_set(error, ZIP_ER_INCONS, 0);
-	    _zip_ef_free(ef_head);
-	    return NULL;
-	}
-
-	if ((ef2=_zip_ef_new(fid, flen, p, flags)) == NULL) {
+        if (ef_data == NULL) {
+            break;
+        }
+        
+	if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
 	    zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_buffer_free(buffer);
 	    _zip_ef_free(ef_head);
 	    return NULL;
 	}
@@ -245,6 +247,15 @@
 	    ef_head = ef = ef2;
     }
 
+    if (!_zip_buffer_eof(buffer)) {
+        zip_error_set(error, ZIP_ER_INCONS, 0);
+        _zip_buffer_free(buffer);
+        _zip_ef_free(ef_head);
+        return NULL;
+    }
+
+    _zip_buffer_free(buffer);
+    
     return ef_head;
 }
 
@@ -297,23 +308,33 @@
 int
 _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
 {
-    zip_uint8_t b[4], *p;
-
+    zip_uint8_t b[4];
+    zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
+    
     for (; ef; ef=ef->next) {
 	if (ef->flags & flags & ZIP_EF_BOTH) {
-	    p = b;
-	    _zip_put_16(&p, ef->id);
-	    _zip_put_16(&p, ef->size);
+            _zip_buffer_set_offset(buffer, 0);
+            _zip_buffer_put_16(buffer, ef->id);
+	    _zip_buffer_put_16(buffer, ef->size);
+            if (!_zip_buffer_ok(buffer)) {
+                zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+                _zip_buffer_free(buffer);
+                return -1;
+            }
 	    if (_zip_write(za, b, 4) < 0) {
-		return -1;
+                _zip_buffer_free(buffer);
+                return -1;
 	    }
 	    if (ef->size > 0) {
 		if (_zip_write(za, ef->data, ef->size) < 0) {
-		    return -1;
+                    _zip_buffer_free(buffer);
+                    return -1;
 		}
 	    }
 	}
     }
+    
+    _zip_buffer_free(buffer);
     return 0;
 }
 
@@ -323,7 +344,7 @@
 {
     zip_entry_t *e;
     unsigned char b[4];
-    const unsigned char *p;
+    zip_buffer_t *buffer;
     zip_uint16_t fname_len, ef_len;
 
     if (idx >= za->nentry) {
@@ -345,15 +366,22 @@
 	_zip_error_set_from_source(&za->error, za->src);
 	return -1;
     }
-
-    if (_zip_read(za->src, b, sizeof(b), &za->error) < 0) {
-	return -1;
+    
+    if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
+        return -1;
     }
-
-    p = b;
-    fname_len = _zip_get_16(&p);
-    ef_len = _zip_get_16(&p);
-
+    
+    fname_len = _zip_buffer_get_16(buffer);
+    ef_len = _zip_buffer_get_16(buffer);
+    
+    if (!_zip_buffer_eof(buffer)) {
+        _zip_buffer_free(buffer);
+        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
+    }
+    
+    _zip_buffer_free(buffer);
+    
     if (ef_len > 0) {
 	zip_extra_field_t *ef;
 	zip_uint8_t *ef_raw;