]> git.imager.perl.org - imager.git/blob - limits.c
- correct documentation of default of raw image interleave read
[imager.git] / limits.c
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  */
26
27 #include "imageri.h"
28
29 static int max_width, max_height;
30 static int max_bytes;
31
32 /*
33 =item i_set_image_file_limits(width, height, bytes)
34
35 =category Files
36 =synopsis i_set_image_file_limits(500, 500, 1000000);
37
38 Set limits on the sizes of images read by Imager.
39
40 Setting a limit to 0 means that limit is ignored.
41
42 Negative limits result in failure.
43
44 Returns non-zero on success.
45
46 =cut
47 */
48
49 int
50 i_set_image_file_limits(int width, int height, int bytes) {
51   i_clear_error();
52
53   if (width < 0) {
54     i_push_error(0, "width must be non-negative");
55     return 0;
56   }
57   if (height < 0) {
58     i_push_error(0, "height must be non-negative");
59     return 0;
60   }
61   if (bytes < 0) {
62     i_push_error(0, "bytes must be non-negative");
63     return 0;
64   }
65
66   max_width = width;
67   max_height = height;
68   max_bytes = bytes;
69
70   return 1;
71 }
72
73 /*
74 =item i_get_image_file_limits(&width, &height, &bytes)
75
76 =category Files
77 =synopsis i_get_image_file_limits(&width, &height, &bytes)
78
79 Retrieves the file limits set by i_set_image_file_limits().
80
81 =cut
82 */
83
84 int
85 i_get_image_file_limits(int *width, int *height, int *bytes) {
86   i_clear_error();
87
88   *width = max_width;
89   *height = max_height;
90   *bytes = max_bytes;
91
92   return 1;
93 }
94
95 /*
96 =item i_int_check_image_file_limits(width, height, channels, sample_size)
97
98 =category Files
99 =synopsis i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
100
101 Checks the size of a file in memory against the configured image file
102 limits.
103
104 This also range checks the values to those permitted by Imager and
105 checks for overflows in calculating the size.
106
107 Returns non-zero if the file is within limits.
108
109 This function is intended to be called by image file read functions.
110
111 =cut
112 */
113
114 int
115 i_int_check_image_file_limits(int width, int height, int channels, int sample_size) {
116   int bytes;
117   i_clear_error();
118   
119   if (width <= 0) {
120     i_push_errorf(0, "file size limit - image width of %d is not positive",
121                   width);
122     return 0;
123   }
124   if (max_width && width > max_width) {
125     i_push_errorf(0, "file size limit - image width of %d exceeds limit of %d",
126                  width, max_width);
127     return 0;
128   }
129
130   if (height <= 0) {
131     i_push_errorf(0, "file size limit - image height %d is not positive",
132                   height);
133     return 0;
134   }
135
136   if (max_height && height > max_height) {
137     i_push_errorf(0, "file size limit - image height of %d "
138                   "exceeds limit of %d", height, max_height);
139     return 0;
140   }
141
142   if (channels < 1 || channels > MAXCHANNELS) {
143     i_push_errorf(0, "file size limit - channels %d out of range",
144                   channels);
145     return 0;
146   }
147   
148   if (sample_size < 1 || sample_size > sizeof(long double)) {
149     i_push_errorf(0, "file size limit - sample_size %d out of range",
150                   sample_size);
151     return 0;
152   }
153
154   /* This overflow check is a bit more paranoid than usual.
155      We don't protect it under max_bytes since we always want to check 
156      for overflow.
157   */
158   bytes = width * height * channels * sample_size;
159   if (bytes / width != height * channels * sample_size
160       || bytes / height != width * channels * sample_size) {
161     i_push_error(0, "file size limit - integer overflow calculating storage");
162     return 0;
163   }
164   if (max_bytes) {
165     if (bytes > max_bytes) {
166       i_push_errorf(0, "file size limit - storage size of %d "
167                     "exceeds limit of %d", bytes, max_bytes);
168       return 0;
169     }
170   }
171
172   return 1;
173 }