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