File Coverage

limits.c
Criterion Covered Total %
statement 45 51 88.2
branch 28 34 82.3
condition n/a
subroutine n/a
pod n/a
total 73 85 85.8


line stmt bran cond sub pod time code
1             /*
2             =head1 NAME
3              
4             limits.c - manages data/functions for limiting the sizes of images read from files.
5              
6             =head1 SYNOPSIS
7              
8             // user code
9             if (!i_set_image_file_limits(max_width, max_height, max_bytes)) {
10             // error
11             }
12             i_get_image_file_limits(&max_width, &max_height, &max_bytes);
13              
14             // file reader implementations
15             if (!i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))) {
16             // error handling
17             }
18              
19             =head1 DESCRIPTION
20              
21             Manage limits for image files read by Imager.
22              
23             Setting a value of zero means that limit will be ignored.
24              
25             =over
26              
27             =cut
28             */
29              
30             #define IMAGER_NO_CONTEXT
31             #include "imageri.h"
32              
33             /*
34             =item im_set_image_file_limits(ctx, width, height, bytes)
35             XX
36             =category Files
37             =synopsis im_set_image_file_limits(aIMCTX, 500, 500, 1000000);
38             =synopsis i_set_image_file_limits(500, 500, 1000000);
39              
40             Set limits on the sizes of images read by Imager.
41              
42             Setting a limit to 0 means that limit is ignored.
43              
44             Negative limits result in failure.
45              
46             Parameters:
47              
48             =over
49              
50             =item *
51              
52             i_img_dim width, height - maximum width and height.
53              
54             =item *
55              
56             size_t bytes - maximum size in memory in bytes. A value of zero sets
57             this limit to one gigabyte.
58              
59             =back
60              
61             Returns non-zero on success.
62              
63             Also callable as C.
64              
65             =cut
66             */
67              
68             int
69 28           im_set_image_file_limits(pIMCTX, i_img_dim width, i_img_dim height, size_t bytes) {
70 28           i_clear_error();
71              
72 28 50         if (width < 0) {
73 0           i_push_error(0, "width must be non-negative");
74 0           return 0;
75             }
76 28 50         if (height < 0) {
77 0           i_push_error(0, "height must be non-negative");
78 0           return 0;
79             }
80              
81 28           aIMCTX->max_width = width;
82 28           aIMCTX->max_height = height;
83 28 100         aIMCTX->max_bytes = bytes ? bytes : DEF_BYTES_LIMIT;
84              
85 28           return 1;
86             }
87              
88             /*
89             =item im_get_image_file_limits(ctx, &width, &height, &bytes)
90             XX
91             =category Files
92             =synopsis im_get_image_file_limits(aIMCTX, &width, &height, &bytes)
93             =synopsis i_get_image_file_limits(&width, &height, &bytes)
94              
95             Retrieves the file limits set by i_set_image_file_limits().
96              
97             =over
98              
99             =item *
100              
101             i_img_dim *width, *height - the maximum width and height of the image.
102              
103             =item *
104              
105             size_t *bytes - size in memory of the image in bytes.
106              
107             =back
108              
109             Also callable as C.
110              
111             =cut
112             */
113              
114             int
115 7           im_get_image_file_limits(pIMCTX, i_img_dim *width, i_img_dim *height, size_t *bytes) {
116 7           im_clear_error(aIMCTX);
117              
118 7           *width = aIMCTX->max_width;
119 7           *height = aIMCTX->max_height;
120 7           *bytes = aIMCTX->max_bytes;
121              
122 7           return 1;
123             }
124              
125             /*
126             =item im_int_check_image_file_limits(width, height, channels, sample_size)
127             XX
128             =category Files
129             =synopsis im_int_check_image_file_limits(aIMCTX, width, height, channels, sizeof(i_sample_t))
130             =synopsis i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
131              
132             Checks the size of a file in memory against the configured image file
133             limits.
134              
135             This also range checks the values to those permitted by Imager and
136             checks for overflows in calculating the size.
137              
138             Returns non-zero if the file is within limits.
139              
140             This function is intended to be called by image file read functions.
141              
142             Also callable as C.
143              
144             =cut
145             */
146              
147             int
148 304           im_int_check_image_file_limits(pIMCTX, i_img_dim width, i_img_dim height, int channels, size_t sample_size) {
149             size_t bytes;
150 304           im_clear_error(aIMCTX);
151            
152 304 100         if (width <= 0) {
153 6           im_push_errorf(aIMCTX, 0, "file size limit - image width of %" i_DF " is not positive",
154             i_DFc(width));
155 6           return 0;
156             }
157 298 100         if (aIMCTX->max_width && width > aIMCTX->max_width) {
    100          
158 5           im_push_errorf(aIMCTX, 0, "file size limit - image width of %" i_DF " exceeds limit of %" i_DF,
159 5           i_DFc(width), i_DFc(aIMCTX->max_width));
160 5           return 0;
161             }
162              
163 293 100         if (height <= 0) {
164 1           im_push_errorf(aIMCTX, 0, "file size limit - image height of %" i_DF " is not positive",
165             i_DFc(height));
166 1           return 0;
167             }
168              
169 292 100         if (aIMCTX->max_height && height > aIMCTX->max_height) {
    100          
170 3           im_push_errorf(aIMCTX, 0, "file size limit - image height of %" i_DF
171 3           " exceeds limit of %" i_DF, i_DFc(height), i_DFc(aIMCTX->max_height));
172 3           return 0;
173             }
174              
175 289 100         if (channels < 1 || channels > MAXCHANNELS) {
    50          
176 1           im_push_errorf(aIMCTX, 0, "file size limit - channels %d out of range",
177             channels);
178 1           return 0;
179             }
180            
181 288 100         if (sample_size < 1 || sample_size > sizeof(long double)) {
    100          
182 2           im_push_errorf(aIMCTX, 0, "file size limit - sample_size %ld out of range",
183             (long)sample_size);
184 2           return 0;
185             }
186              
187             /* This overflow check is a bit more paranoid than usual.
188             We don't protect it under max_bytes since we always want to check
189             for overflow.
190             */
191 286           bytes = width * height * channels * sample_size;
192 286 50         if (bytes / width != height * channels * sample_size
193 286 50         || bytes / height != width * channels * sample_size) {
194 0           im_push_error(aIMCTX, 0, "file size limit - integer overflow calculating storage");
195 0           return 0;
196             }
197 286 50         if (aIMCTX->max_bytes) {
198 286 100         if (bytes > aIMCTX->max_bytes) {
199 4           im_push_errorf(aIMCTX, 0, "file size limit - storage size of %lu "
200             "exceeds limit of %lu", (unsigned long)bytes,
201 4           (unsigned long)aIMCTX->max_bytes);
202 4           return 0;
203             }
204             }
205              
206 282           return 1;
207             }