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