diff options
Diffstat (limited to 'src/plugins/gif_extractor.c')
-rw-r--r-- | src/plugins/gif_extractor.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/src/plugins/gif_extractor.c b/src/plugins/gif_extractor.c index 69760eb..055fd9f 100644 --- a/src/plugins/gif_extractor.c +++ b/src/plugins/gif_extractor.c | |||
@@ -29,12 +29,12 @@ | |||
29 | #define PRINT(a,b) | 29 | #define PRINT(a,b) |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | typedef struct | 32 | struct GifHeader |
33 | { | 33 | { |
34 | char gif[3]; | 34 | char gif[3]; |
35 | char version[3]; | 35 | char version[3]; |
36 | unsigned short screen_width; | 36 | uint16_t screen_width; |
37 | unsigned short screen_height; | 37 | uint16_t screen_height; |
38 | unsigned char flags; | 38 | unsigned char flags; |
39 | #define HEADER_FLAGS__SIZE_OF_GLOBAL_COLOR_TABLE 0x07 | 39 | #define HEADER_FLAGS__SIZE_OF_GLOBAL_COLOR_TABLE 0x07 |
40 | #define HEADER_FLAGS__SORT_FLAG 0x08 | 40 | #define HEADER_FLAGS__SORT_FLAG 0x08 |
@@ -42,7 +42,7 @@ typedef struct | |||
42 | #define HEADER_FLAGS__GLOBAL_COLOR_TABLE_FLAG 0x80 | 42 | #define HEADER_FLAGS__GLOBAL_COLOR_TABLE_FLAG 0x80 |
43 | unsigned char background_color_index; | 43 | unsigned char background_color_index; |
44 | unsigned char pixel_aspect_ratio; | 44 | unsigned char pixel_aspect_ratio; |
45 | } GIF_HEADER; | 45 | }; |
46 | 46 | ||
47 | #define GIF_HEADER_SIZE 13 | 47 | #define GIF_HEADER_SIZE 13 |
48 | #define GIF_HEADER_SPEC "3b3bhhbbb" | 48 | #define GIF_HEADER_SPEC "3b3bhhbbb" |
@@ -55,20 +55,21 @@ typedef struct | |||
55 | &(p)->background_color_index, \ | 55 | &(p)->background_color_index, \ |
56 | &(p)->pixel_aspect_ratio | 56 | &(p)->pixel_aspect_ratio |
57 | 57 | ||
58 | typedef struct | 58 | struct GifDescriptor |
59 | { | 59 | { |
60 | unsigned char image_separator; | 60 | unsigned char image_separator; |
61 | unsigned short image_left; | 61 | uint16_t image_left; |
62 | unsigned short image_top; | 62 | uint16_t image_top; |
63 | unsigned short image_width; | 63 | uint16_t image_width; |
64 | unsigned short image_height; | 64 | uint16_t image_height; |
65 | unsigned char flags; | 65 | unsigned char flags; |
66 | #define DESCRIPTOR_FLAGS__PIXEL_SIZE 0x07 | 66 | #define DESCRIPTOR_FLAGS__PIXEL_SIZE 0x07 |
67 | #define DESCRIPTOR_FLAGS__RESERVED 0x18 | 67 | #define DESCRIPTOR_FLAGS__RESERVED 0x18 |
68 | #define DESCRIPTOR_FLAGS__SORT_FLAG 0x20 | 68 | #define DESCRIPTOR_FLAGS__SORT_FLAG 0x20 |
69 | #define DESCRIPTOR_FLAGS__INTERLACE_FLAG 0x40 | 69 | #define DESCRIPTOR_FLAGS__INTERLACE_FLAG 0x40 |
70 | #define DESCRIPTOR_FLAGS__LOCAL_COLOR_TABLE_FLAG 0x80 | 70 | #define DESCRIPTOR_FLAGS__LOCAL_COLOR_TABLE_FLAG 0x80 |
71 | } GIF_DESCRIPTOR; | 71 | }; |
72 | |||
72 | #define GIF_DESCRIPTOR_SIZE 10 | 73 | #define GIF_DESCRIPTOR_SIZE 10 |
73 | #define GIF_DESCRIPTOR_SPEC "chhhhc" | 74 | #define GIF_DESCRIPTOR_SPEC "chhhhc" |
74 | #define GIF_DESCRIPTOR_FIELDS(p) \ | 75 | #define GIF_DESCRIPTOR_FIELDS(p) \ |
@@ -79,16 +80,16 @@ typedef struct | |||
79 | &(p)->image_height, \ | 80 | &(p)->image_height, \ |
80 | &(p)->flags | 81 | &(p)->flags |
81 | 82 | ||
82 | typedef struct | 83 | struct GifExtension |
83 | { | 84 | { |
84 | unsigned char extension_introducer; | 85 | unsigned char extension_introducer; |
85 | unsigned char graphic_control_label; | 86 | unsigned char graphic_control_label; |
86 | } GIF_EXTENSION; | 87 | }; |
87 | 88 | ||
88 | /** | 89 | /** |
89 | * Skip a data block. | 90 | * Skip a data block. |
90 | * @return the position after the block | 91 | * @return the position after the block |
91 | **/ | 92 | */ |
92 | static size_t | 93 | static size_t |
93 | skipDataBlock (const unsigned char *data, size_t pos, const size_t size) | 94 | skipDataBlock (const unsigned char *data, size_t pos, const size_t size) |
94 | { | 95 | { |
@@ -100,20 +101,22 @@ skipDataBlock (const unsigned char *data, size_t pos, const size_t size) | |||
100 | /** | 101 | /** |
101 | * skip an extention block | 102 | * skip an extention block |
102 | * @return the position after the block | 103 | * @return the position after the block |
103 | **/ | 104 | */ |
104 | static size_t | 105 | static size_t |
105 | skipExtensionBlock (const unsigned char *data, | 106 | skipExtensionBlock (const unsigned char *data, |
106 | size_t pos, const size_t size, const GIF_EXTENSION * ext) | 107 | size_t pos, const size_t size, |
108 | const struct GifExtension * ext) | ||
107 | { | 109 | { |
108 | return skipDataBlock (data, pos + sizeof (GIF_EXTENSION), size); | 110 | return skipDataBlock (data, pos + sizeof (struct GifExtension), size); |
109 | } | 111 | } |
110 | 112 | ||
111 | /** | 113 | /** |
112 | * @return the offset after the global color map | 114 | * @return the offset after the global color map |
113 | **/ | 115 | */ |
114 | static size_t | 116 | static size_t |
115 | skipGlobalColorMap (const unsigned char *data, | 117 | skipGlobalColorMap (const unsigned char *data, |
116 | const size_t size, const GIF_HEADER * header) | 118 | const size_t size, |
119 | const struct GifHeader * header) | ||
117 | { | 120 | { |
118 | size_t gct_size; | 121 | size_t gct_size; |
119 | 122 | ||
@@ -128,10 +131,11 @@ skipGlobalColorMap (const unsigned char *data, | |||
128 | 131 | ||
129 | /** | 132 | /** |
130 | * @return the offset after the local color map | 133 | * @return the offset after the local color map |
131 | **/ | 134 | */ |
132 | static size_t | 135 | static size_t |
133 | skipLocalColorMap (const unsigned char *data, | 136 | skipLocalColorMap (const unsigned char *data, |
134 | size_t pos, const size_t size, GIF_DESCRIPTOR * descriptor) | 137 | size_t pos, const size_t size, |
138 | const struct GifDescriptor * descriptor) | ||
135 | { | 139 | { |
136 | size_t lct_size; | 140 | size_t lct_size; |
137 | 141 | ||
@@ -151,31 +155,38 @@ parseComment (const unsigned char *data, | |||
151 | EXTRACTOR_MetaDataProcessor proc, | 155 | EXTRACTOR_MetaDataProcessor proc, |
152 | void *proc_cls) | 156 | void *proc_cls) |
153 | { | 157 | { |
154 | size_t length = 0; | 158 | size_t length; |
159 | size_t off; | ||
155 | size_t curr = pos; | 160 | size_t curr = pos; |
156 | int ret; | 161 | int ret; |
157 | 162 | ||
158 | while ((data[curr] != 0) && (curr < size)) | 163 | length = 0; |
164 | while ( (curr < size) && | ||
165 | (data[curr] != 0) ) | ||
159 | { | 166 | { |
160 | length += data[curr]; | 167 | length += data[curr]; |
161 | curr += data[curr] + 1; | 168 | curr += data[curr] + 1; |
162 | if (length > 65536) | 169 | if (length > 65536) |
163 | break; | 170 | break; |
164 | } | 171 | } |
165 | if (length < 65536) | 172 | if ( (length < 65536) && |
173 | (curr < size) ) | ||
166 | { | 174 | { |
167 | char comment[length+1]; | 175 | char comment[length+1]; |
176 | |||
168 | curr = pos; | 177 | curr = pos; |
169 | length = 0; | 178 | off = 0; |
170 | while ((data[curr] != 0) && (curr < size)) | 179 | while ((data[curr] != 0) && (curr < size)) |
171 | { | 180 | { |
172 | length += data[curr]; | 181 | if (off + data[curr] >= size) |
173 | if (length >= size) | ||
174 | break; | 182 | break; |
175 | memcpy (&comment[length - data[curr]], &data[curr] + 1, data[curr]); | 183 | memcpy (&comment[off], |
176 | comment[length] = '\0'; | 184 | &data[curr] + 1, |
185 | data[curr]); | ||
186 | off += data[curr]; | ||
177 | curr += data[curr] + 1; | 187 | curr += data[curr] + 1; |
178 | } | 188 | } |
189 | comment[off] = '\0'; | ||
179 | ret = proc (proc_cls, | 190 | ret = proc (proc_cls, |
180 | "gif", | 191 | "gif", |
181 | EXTRACTOR_METATYPE_COMMENT, | 192 | EXTRACTOR_METATYPE_COMMENT, |
@@ -186,6 +197,7 @@ parseComment (const unsigned char *data, | |||
186 | } | 197 | } |
187 | else | 198 | else |
188 | { | 199 | { |
200 | /* too big */ | ||
189 | ret = 0; | 201 | ret = 0; |
190 | } | 202 | } |
191 | return ret; | 203 | return ret; |
@@ -200,7 +212,8 @@ EXTRACTOR_gif_extract (const unsigned char *data, | |||
200 | const char *options) | 212 | const char *options) |
201 | { | 213 | { |
202 | size_t pos; | 214 | size_t pos; |
203 | GIF_HEADER header; | 215 | struct GifHeader header; |
216 | struct GifDescriptor gd; | ||
204 | char tmp[128]; | 217 | char tmp[128]; |
205 | 218 | ||
206 | if (size < GIF_HEADER_SIZE) | 219 | if (size < GIF_HEADER_SIZE) |
@@ -234,8 +247,6 @@ EXTRACTOR_gif_extract (const unsigned char *data, | |||
234 | PRINT ("global color map ends at %d\n", pos); | 247 | PRINT ("global color map ends at %d\n", pos); |
235 | while (pos < size) | 248 | while (pos < size) |
236 | { | 249 | { |
237 | GIF_DESCRIPTOR gd; | ||
238 | |||
239 | switch (data[pos]) | 250 | switch (data[pos]) |
240 | { | 251 | { |
241 | case ',': /* image descriptor block */ | 252 | case ',': /* image descriptor block */ |
@@ -253,7 +264,7 @@ EXTRACTOR_gif_extract (const unsigned char *data, | |||
253 | return 1; | 264 | return 1; |
254 | } | 265 | } |
255 | pos = skipExtensionBlock (data, pos, size, | 266 | pos = skipExtensionBlock (data, pos, size, |
256 | (GIF_EXTENSION *) & data[pos]); | 267 | (const struct GifExtension *) & data[pos]); |
257 | break; | 268 | break; |
258 | case ';': | 269 | case ';': |
259 | PRINT ("hit terminator at %d!\n", pos); | 270 | PRINT ("hit terminator at %d!\n", pos); |