From e062eb8589583644760fa38a312dd5aad07882a7 Mon Sep 17 00:00:00 2001
From: Bastian Kleineidam <calvin@debian.org>
Date: Fri, 25 Jan 2008 17:17:59 +0100
Subject: Prevent file descriptor leaks
Wrap all opened files in try-finally blocks and close the
descriptors.
Signed-off-by: Bastian Kleineidam <calvin@debian.org>
diff --git a/django/bin/make-messages.py b/django/bin/make-messages.py
index 4404039..4cd0fc3 100755
a
|
b
|
def make_messages():
|
81 | 81 | for dirpath, file in all_files: |
82 | 82 | if domain == 'djangojs' and file.endswith('.js'): |
83 | 83 | if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) |
84 | | src = open(os.path.join(dirpath, file), "rb").read() |
| 84 | f = open(os.path.join(dirpath, file), "rb") |
| 85 | try: |
| 86 | src = f.read() |
| 87 | finally: |
| 88 | f.close() |
85 | 89 | src = pythonize_re.sub('\n#', src) |
86 | | open(os.path.join(dirpath, '%s.py' % file), "wb").write(src) |
| 90 | f = open(os.path.join(dirpath, '%s.py' % file), "wb") |
| 91 | try: |
| 92 | f.write(src) |
| 93 | finally: |
| 94 | f.close() |
87 | 95 | thefile = '%s.py' % file |
88 | 96 | cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( |
89 | 97 | os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile)) |
… |
… |
def make_messages():
|
98 | 106 | new = '#: '+os.path.join(dirpath, file)[2:] |
99 | 107 | msgs = msgs.replace(old, new) |
100 | 108 | if msgs: |
101 | | open(potfile, 'ab').write(msgs) |
| 109 | f = open(potfile, 'ab') |
| 110 | try: |
| 111 | f.write(msgs) |
| 112 | finally: |
| 113 | f.close() |
102 | 114 | os.unlink(os.path.join(dirpath, thefile)) |
103 | 115 | elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')): |
104 | 116 | thefile = file |
105 | 117 | if file.endswith('.html'): |
106 | | src = open(os.path.join(dirpath, file), "rb").read() |
| 118 | f = open(os.path.join(dirpath, file), "rb") |
| 119 | try: |
| 120 | src = f.read() |
| 121 | finally: |
| 122 | f.close() |
107 | 123 | thefile = '%s.py' % file |
108 | | open(os.path.join(dirpath, thefile), "wb").write(templatize(src)) |
| 124 | f = open(os.path.join(dirpath, thefile), "wb") |
| 125 | try: |
| 126 | f.write(templatize(src)) |
| 127 | finally: |
| 128 | f.close() |
109 | 129 | if verbose: |
110 | 130 | sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) |
111 | 131 | cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( |
… |
… |
def make_messages():
|
127 | 147 | else: |
128 | 148 | msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') |
129 | 149 | if msgs: |
130 | | open(potfile, 'ab').write(msgs) |
| 150 | f = open(potfile, 'ab') |
| 151 | try: |
| 152 | f.write(msgs) |
| 153 | finally: |
| 154 | f.close() |
131 | 155 | if thefile != file: |
132 | 156 | os.unlink(os.path.join(dirpath, thefile)) |
133 | 157 | |
… |
… |
def make_messages():
|
139 | 163 | print "errors happened while running msguniq" |
140 | 164 | print errors |
141 | 165 | sys.exit(8) |
142 | | open(potfile, 'w').write(msgs) |
| 166 | f = open(potfile, 'w') |
| 167 | try: |
| 168 | f.write(msgs) |
| 169 | finally: |
| 170 | f.close() |
143 | 171 | if os.path.exists(pofile): |
144 | 172 | (stdin, stdout, stderr) = os.popen3('msgmerge -q "%s" "%s"' % (pofile, potfile), 'b') |
145 | 173 | msgs = stdout.read() |
… |
… |
def make_messages():
|
148 | 176 | print "errors happened while running msgmerge" |
149 | 177 | print errors |
150 | 178 | sys.exit(8) |
151 | | open(pofile, 'wb').write(msgs) |
| 179 | f = open(pofile, 'wb') |
| 180 | try: |
| 181 | f.write(msgs) |
| 182 | finally: |
| 183 | f.close() |
152 | 184 | os.unlink(potfile) |
153 | 185 | |
154 | 186 | if __name__ == "__main__": |
diff --git a/django/bin/unique-messages.py b/django/bin/unique-messages.py
index c601a9e..d26635d 100755
a
|
b
|
def unique_messages():
|
22 | 22 | cmd = 'msguniq "%s.po"' % pf |
23 | 23 | stdout = os.popen(cmd) |
24 | 24 | msg = stdout.read() |
25 | | open('%s.po' % pf, 'w').write(msg) |
| 25 | f = open('%s.po' % pf, 'w') |
| 26 | try: |
| 27 | f.write(msg) |
| 28 | finally: |
| 29 | f.close() |
26 | 30 | |
27 | 31 | if __name__ == "__main__": |
28 | 32 | unique_messages() |
diff --git a/django/contrib/admin/views/doc.py b/django/contrib/admin/views/doc.py
index 44a27d6..955d06d 100644
a
|
b
|
def model_detail(request, app_label, model_name):
|
234 | 234 | }, context_instance=RequestContext(request)) |
235 | 235 | model_detail = staff_member_required(model_detail) |
236 | 236 | |
| 237 | def get_template_contents (filename): |
| 238 | if os.path.exists(filename): |
| 239 | fd = open(filename) |
| 240 | try: |
| 241 | return fd.read() |
| 242 | finally: |
| 243 | fd.close() |
| 244 | return '' |
| 245 | |
237 | 246 | def template_detail(request, template): |
238 | 247 | templates = [] |
239 | 248 | for site_settings_module in settings.ADMIN_FOR: |
… |
… |
def template_detail(request, template):
|
247 | 256 | templates.append({ |
248 | 257 | 'file': template_file, |
249 | 258 | 'exists': os.path.exists(template_file), |
250 | | 'contents': lambda: os.path.exists(template_file) and open(template_file).read() or '', |
| 259 | 'contents': lambda: get_template_contents(template_file), |
251 | 260 | 'site_id': settings_mod.SITE_ID, |
252 | 261 | 'site': site_obj, |
253 | 262 | 'order': list(settings_mod.TEMPLATE_DIRS).index(dir), |
diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py
index c1277bf..7483720 100644
a
|
b
|
class CacheClass(BaseCache):
|
38 | 38 | fname = self._key_to_file(key) |
39 | 39 | try: |
40 | 40 | f = open(fname, 'rb') |
41 | | exp = pickle.load(f) |
42 | | now = time.time() |
43 | | if exp < now: |
| 41 | try: |
| 42 | exp = pickle.load(f) |
| 43 | now = time.time() |
| 44 | if exp < now: |
| 45 | f.close() |
| 46 | self._delete(fname) |
| 47 | else: |
| 48 | return pickle.load(f) |
| 49 | finally: |
| 50 | # note: calling f.close() twice is ok |
44 | 51 | f.close() |
45 | | self._delete(fname) |
46 | | else: |
47 | | return pickle.load(f) |
48 | 52 | except (IOError, OSError, EOFError, pickle.PickleError): |
49 | 53 | pass |
50 | 54 | return default |
… |
… |
class CacheClass(BaseCache):
|
63 | 67 | os.makedirs(dirname) |
64 | 68 | |
65 | 69 | f = open(fname, 'wb') |
66 | | now = time.time() |
67 | | pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL) |
68 | | pickle.dump(value, f, pickle.HIGHEST_PROTOCOL) |
| 70 | try: |
| 71 | now = time.time() |
| 72 | pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL) |
| 73 | pickle.dump(value, f, pickle.HIGHEST_PROTOCOL) |
| 74 | finally: |
| 75 | f.close() |
69 | 76 | except (IOError, OSError): |
70 | 77 | pass |
71 | 78 | |
… |
… |
class CacheClass(BaseCache):
|
89 | 96 | fname = self._key_to_file(key) |
90 | 97 | try: |
91 | 98 | f = open(fname, 'rb') |
92 | | exp = pickle.load(f) |
93 | | now = time.time() |
94 | | if exp < now: |
| 99 | try: |
| 100 | exp = pickle.load(f) |
| 101 | now = time.time() |
| 102 | if exp < now: |
| 103 | f.close() |
| 104 | self._delete(fname) |
| 105 | return False |
| 106 | else: |
| 107 | return True |
| 108 | finally: |
| 109 | # note: calling f.close() twice is ok |
95 | 110 | f.close() |
96 | | self._delete(fname) |
97 | | return False |
98 | | else: |
99 | | return True |
100 | 111 | except (IOError, OSError, EOFError, pickle.PickleError): |
101 | 112 | return False |
102 | 113 | |
diff --git a/django/core/mail.py b/django/core/mail.py
index 153dcb6..65b123b 100644
a
|
b
|
class EmailMessage(object):
|
273 | 273 | def attach_file(self, path, mimetype=None): |
274 | 274 | """Attaches a file from the filesystem.""" |
275 | 275 | filename = os.path.basename(path) |
276 | | content = open(path, 'rb').read() |
| 276 | f = open(path, 'rb') |
| 277 | try: |
| 278 | content = f.read() |
| 279 | finally: |
| 280 | f.close() |
277 | 281 | self.attach(filename, content, mimetype) |
278 | 282 | |
279 | 283 | def _create_attachment(self, filename, content, mimetype=None): |
diff --git a/django/core/management/base.py b/django/core/management/base.py
index 7b8a3e9..a192b87 100644
a
|
b
|
def copy_helper(style, app_or_project, name, directory, other_name=''):
|
210 | 210 | path_old = os.path.join(d, f) |
211 | 211 | path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name)) |
212 | 212 | fp_old = open(path_old, 'r') |
| 213 | try: |
| 214 | content = fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name) |
| 215 | finally: |
| 216 | fp_old.close() |
213 | 217 | fp_new = open(path_new, 'w') |
214 | | fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name)) |
215 | | fp_old.close() |
216 | | fp_new.close() |
| 218 | try: |
| 219 | fp_new.write(content) |
| 220 | finally: |
| 221 | fp_new.close() |
217 | 222 | try: |
218 | 223 | shutil.copymode(path_old, path_new) |
219 | 224 | _make_writeable(path_new) |
diff --git a/django/core/management/commands/startproject.py b/django/core/management/commands/startproject.py
index ab4f409..560998e 100644
a
|
b
|
class Command(LabelCommand):
|
27 | 27 | |
28 | 28 | # Create a random SECRET_KEY hash, and put it in the main settings. |
29 | 29 | main_settings_file = os.path.join(directory, project_name, 'settings.py') |
30 | | settings_contents = open(main_settings_file, 'r').read() |
31 | | fp = open(main_settings_file, 'w') |
| 30 | f = open(main_settings_file, 'r') |
| 31 | try: |
| 32 | settings_contents = f.read() |
| 33 | finally: |
| 34 | f.close() |
32 | 35 | secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)]) |
33 | 36 | settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents) |
34 | | fp.write(settings_contents) |
35 | | fp.close() |
| 37 | fp = open(main_settings_file, 'w') |
| 38 | try: |
| 39 | fp.write(settings_contents) |
| 40 | finally: |
| 41 | fp.close() |
diff --git a/django/core/management/sql.py b/django/core/management/sql.py
index 15bffce..fd37d6d 100644
a
|
b
|
def custom_sql_for_model(model):
|
443 | 443 | for sql_file in sql_files: |
444 | 444 | if os.path.exists(sql_file): |
445 | 445 | fp = open(sql_file, 'U') |
446 | | for statement in statements.split(fp.read().decode(settings.FILE_CHARSET)): |
| 446 | try: |
| 447 | content = fp.read().decode(settings.FILE_CHARSET) |
| 448 | finally: |
| 449 | fp.close() |
| 450 | for statement in statements.split(content): |
447 | 451 | # Remove any comments from the file |
448 | 452 | statement = re.sub(ur"--.*[\n\Z]", "", statement) |
449 | 453 | if statement.strip(): |
450 | 454 | output.append(statement + u";") |
451 | | fp.close() |
452 | 455 | |
453 | 456 | return output |
454 | 457 | |
diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index 05f8756..ac5cd86 100644
a
|
b
|
class AdminMediaHandler(object):
|
645 | 645 | headers = {'Content-type': 'text/plain'} |
646 | 646 | output = ['Permission denied: %s' % file_path] |
647 | 647 | else: |
648 | | status = '200 OK' |
649 | | headers = {} |
650 | | mime_type = mimetypes.guess_type(file_path)[0] |
651 | | if mime_type: |
652 | | headers['Content-Type'] = mime_type |
653 | | output = [fp.read()] |
654 | | fp.close() |
| 648 | try: |
| 649 | status = '200 OK' |
| 650 | headers = {} |
| 651 | mime_type = mimetypes.guess_type(file_path)[0] |
| 652 | if mime_type: |
| 653 | headers['Content-Type'] = mime_type |
| 654 | output = [fp.read()] |
| 655 | finally: |
| 656 | fp.close() |
655 | 657 | start_response(status, headers.items()) |
656 | 658 | return output |
657 | 659 | |
diff --git a/django/core/servers/fastcgi.py b/django/core/servers/fastcgi.py
index de04a5a..82c53c9 100644
a
|
b
|
def runfastcgi(argset=[], **kwargs):
|
155 | 155 | become_daemon(our_home_dir=options["workdir"]) |
156 | 156 | |
157 | 157 | if options["pidfile"]: |
158 | | fp = open(options["pidfile"], "w") |
159 | | fp.write("%d\n" % os.getpid()) |
160 | | fp.close() |
| 158 | f = open(options["pidfile"], "w") |
| 159 | try: |
| 160 | f.write("%d\n" % os.getpid()) |
| 161 | finally: |
| 162 | f.close() |
161 | 163 | |
162 | 164 | WSGIServer(WSGIHandler(), **wsgi_opts).run() |
163 | 165 | |
diff --git a/django/core/validators.py b/django/core/validators.py
index 874edae..a051077 100644
a
|
b
|
class RelaxNGCompact(object):
|
553 | 553 | 'data': field_data |
554 | 554 | } |
555 | 555 | filename = tempfile.mktemp() # Insecure, but nothing else worked |
556 | | fp = open(filename, 'w') |
557 | | fp.write(field_data) |
558 | | fp.close() |
| 556 | f = open(filename, 'w') |
| 557 | try: |
| 558 | f.write(field_data) |
| 559 | finally: |
| 560 | f.close() |
559 | 561 | if not os.path.exists(settings.JING_PATH): |
560 | 562 | raise Exception, "%s not found!" % settings.JING_PATH |
561 | 563 | p = os.popen('%s -c %s %s' % (settings.JING_PATH, self.schema_path, filename)) |
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 31bc907..b6c9948 100644
a
|
b
|
class Model(object):
|
403 | 403 | setattr(self, field.attname, filename) |
404 | 404 | |
405 | 405 | full_filename = self._get_FIELD_filename(field) |
406 | | fp = open(full_filename, 'wb') |
407 | | fp.write(raw_contents) |
408 | | fp.close() |
| 406 | f = open(full_filename, 'wb') |
| 407 | try: |
| 408 | f.write(raw_contents) |
| 409 | finally: |
| 410 | f.close() |
409 | 411 | |
410 | 412 | # Save the width and/or height, if applicable. |
411 | 413 | if isinstance(field, ImageField) and (field.width_field or field.height_field): |
diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index e5a8e66..27e8339 100644
a
|
b
|
class SsiNode(Node):
|
293 | 293 | else: |
294 | 294 | return '' # Fail silently for invalid includes. |
295 | 295 | try: |
296 | | fp = open(self.filepath, 'r') |
297 | | output = fp.read() |
298 | | fp.close() |
| 296 | f = open(self.filepath, 'r') |
| 297 | try: |
| 298 | output = f.read() |
| 299 | finally: |
| 300 | f.close() |
299 | 301 | except IOError: |
300 | 302 | output = '' |
301 | 303 | if self.parsed: |
diff --git a/django/template/loaders/app_directories.py b/django/template/loaders/app_directories.py
index f0f4b1a..6684acd 100644
a
|
b
|
def get_template_sources(template_name, template_dirs=None):
|
45 | 45 | def load_template_source(template_name, template_dirs=None): |
46 | 46 | for filepath in get_template_sources(template_name, template_dirs): |
47 | 47 | try: |
48 | | return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) |
| 48 | f = open(filepath) |
| 49 | try: |
| 50 | content = f.read().decode(settings.FILE_CHARSET) |
| 51 | finally: |
| 52 | f.close() |
| 53 | return (content, filepath) |
49 | 54 | except IOError: |
50 | 55 | pass |
51 | 56 | raise TemplateDoesNotExist, template_name |
diff --git a/django/template/loaders/filesystem.py b/django/template/loaders/filesystem.py
index 9997eb9..37f9036 100644
a
|
b
|
def load_template_source(template_name, template_dirs=None):
|
20 | 20 | tried = [] |
21 | 21 | for filepath in get_template_sources(template_name, template_dirs): |
22 | 22 | try: |
23 | | return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) |
| 23 | f = open(filepath) |
| 24 | try: |
| 25 | content = f.read().decode(settings.FILE_CHARSET) |
| 26 | finally: |
| 27 | f.close() |
| 28 | return (content, filepath) |
24 | 29 | except IOError: |
25 | 30 | tried.append(filepath) |
26 | 31 | if tried: |
diff --git a/django/test/_doctest.py b/django/test/_doctest.py
index a56483c..ae5c4ad 100644
a
|
b
|
def testfile(filename, module_relative=True, name=None, package=None,
|
1982 | 1982 | runner = DocTestRunner(verbose=verbose, optionflags=optionflags) |
1983 | 1983 | |
1984 | 1984 | # Read the file, convert it to a test, and run it. |
1985 | | s = open(filename).read() |
| 1985 | f = open(filename) |
| 1986 | try: |
| 1987 | s = f.read() |
| 1988 | finally: |
| 1989 | f.close() |
1986 | 1990 | test = parser.get_doctest(s, globs, name, filename, 0) |
1987 | 1991 | runner.run(test) |
1988 | 1992 | |
… |
… |
def DocFileTest(path, module_relative=True, package=None,
|
2368 | 2372 | |
2369 | 2373 | # Find the file and read it. |
2370 | 2374 | name = os.path.basename(path) |
2371 | | doc = open(path).read() |
| 2375 | f = open(path) |
| 2376 | try: |
| 2377 | doc = f.read() |
| 2378 | finally: |
| 2379 | f.close() |
2372 | 2380 | |
2373 | 2381 | # Convert it to a test, and wrap it in a DocFileCase. |
2374 | 2382 | test = parser.get_doctest(doc, globs, name, path, 0) |
… |
… |
def debug_script(src, pm=False, globs=None):
|
2554 | 2562 | # on modern Windows boxes, and execfile() needs to open it. |
2555 | 2563 | srcfilename = tempfile.mktemp(".py", "doctestdebug") |
2556 | 2564 | f = open(srcfilename, 'w') |
2557 | | f.write(src) |
2558 | | f.close() |
| 2565 | try: |
| 2566 | f.write(src) |
| 2567 | finally: |
| 2568 | f.close() |
2559 | 2569 | |
2560 | 2570 | try: |
2561 | 2571 | if globs: |
diff --git a/django/utils/images.py b/django/utils/images.py
index 122c6ae..35d51ed 100644
a
|
b
|
import ImageFile
|
9 | 9 | def get_image_dimensions(path): |
10 | 10 | """Returns the (width, height) of an image at a given path.""" |
11 | 11 | p = ImageFile.Parser() |
12 | | fp = open(path, 'rb') |
13 | | while 1: |
14 | | data = fp.read(1024) |
15 | | if not data: |
16 | | break |
17 | | p.feed(data) |
18 | | if p.image: |
19 | | return p.image.size |
20 | | break |
21 | | fp.close() |
| 12 | f = open(path, 'rb') |
| 13 | try: |
| 14 | while 1: |
| 15 | data = f.read(1024) |
| 16 | if not data: |
| 17 | break |
| 18 | p.feed(data) |
| 19 | if p.image: |
| 20 | return p.image.size |
| 21 | break |
| 22 | finally: |
| 23 | f.close() |
22 | 24 | return None |
diff --git a/django/utils/version.py b/django/utils/version.py
index cf80856..350da4a 100644
a
|
b
|
def get_svn_revision(path=None):
|
20 | 20 | entries_path = '%s/.svn/entries' % path |
21 | 21 | |
22 | 22 | if os.path.exists(entries_path): |
23 | | entries = open(entries_path, 'r').read() |
| 23 | f = open(entries_path, 'r') |
| 24 | try: |
| 25 | entries = f.read() |
| 26 | finally: |
| 27 | f.close() |
24 | 28 | # Versions >= 7 of the entries file are flat text. The first line is |
25 | 29 | # the version number. The next set of digits after 'dir' is the revision. |
26 | 30 | if re.match('(\d+)', entries): |
diff --git a/django/views/static.py b/django/views/static.py
index 5a4d3ab..e010a18 100644
a
|
b
|
def serve(request, path, document_root=None, show_indexes=False):
|
60 | 60 | statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): |
61 | 61 | return HttpResponseNotModified() |
62 | 62 | mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream' |
63 | | contents = open(fullpath, 'rb').read() |
| 63 | f = open(fullpath, 'rb') |
| 64 | try: |
| 65 | contents = f.read() |
| 66 | finally: |
| 67 | f.close() |
64 | 68 | response = HttpResponse(contents, mimetype=mimetype) |
65 | 69 | response["Last-Modified"] = http_date(statobj[stat.ST_MTIME]) |
66 | 70 | response["Content-Length"] = len(contents) |