- start of external Imager API access:
[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 int
33 i_set_image_file_limits(int width, int height, int bytes) {
34   i_clear_error();
35
36   if (width < 0) {
37     i_push_error(0, "width must be non-negative");
38     return 0;
39   }
40   if (height < 0) {
41     i_push_error(0, "height must be non-negative");
42     return 0;
43   }
44   if (bytes < 0) {
45     i_push_error(0, "bytes must be non-negative");
46     return 0;
47   }
48
49   max_width = width;
50   max_height = height;
51   max_bytes = bytes;
52
53   return 1;
54 }
55
56 int
57 i_get_image_file_limits(int *width, int *height, int *bytes) {
58   i_clear_error();
59
60   *width = max_width;
61   *height = max_height;
62   *bytes = max_bytes;
63
64   return 1;
65 }
66
67 int
68 i_int_check_image_file_limits(int width, int height, int channels, int sample_size) {
69   int bytes;
70   i_clear_error();
71   
72   if (width <= 0) {
73     i_push_errorf(0, "file size limit - image width of %d is not positive",
74                   width);
75     return 0;
76   }
77   if (max_width && width > max_width) {
78     i_push_errorf(0, "file size limit - image width of %d exceeds limit of %d",
79                  width, max_width);
80     return 0;
81   }
82
83   if (height <= 0) {
84     i_push_errorf(0, "file size limit - image height %d is not positive",
85                   height);
86     return 0;
87   }
88
89   if (max_height && height > max_height) {
90     i_push_errorf(0, "file size limit - image height of %d "
91                   "exceeds limit of %d", height, max_height);
92     return 0;
93   }
94
95   if (channels < 1 || channels > MAXCHANNELS) {
96     i_push_errorf(0, "file size limit - channels %d out of range",
97                   channels);
98     return 0;
99   }
100   
101   if (sample_size < 1 || sample_size > sizeof(long double)) {
102     i_push_errorf(0, "file size limit - sample_size %d out of range",
103                   sample_size);
104     return 0;
105   }
106
107   /* This overflow check is a bit more paranoid than usual.
108      We don't protect it under max_bytes since we always want to check 
109      for overflow.
110   */
111   bytes = width * height * channels * sample_size;
112   if (bytes / width != height * channels * sample_size
113       || bytes / height != width * channels * sample_size) {
114     i_push_error(0, "file size limit - integer overflow calculating storage");
115     return 0;
116   }
117   if (max_bytes) {
118     if (bytes > max_bytes) {
119       i_push_errorf(0, "file size limit - storage size of %d "
120                     "exceeds limit of %d", bytes, max_bytes);
121       return 0;
122     }
123   }
124
125   return 1;
126 }