Opened 7 years ago

Closed 3 years ago

#28154 closed Bug (fixed)

Infinite loop in collectstatic with broken symlinks

Reported by: Matthew Somerville Owned by: Jacob Walls
Component: File uploads/storage Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

If the static directory contains a broken symlink in place of a file that collectstatic wishes to copy*, then the code gets stuck in an infinite loop, because the os.open fails (O_CREAT | O_EXCL will fail if a symlink exists, even if it's to a non-existent file), but then get_available_name returns the same name (as it calls self.exists, which returns False for a broken symlink).

I guess two possibilities are:

  1. don't care about broken symlinks. Change the flags setting in django/core/files/storage.py to not include O_EXCL if os.path.islink(full_path) and not os.path.exists(full_path).
  2. do care, change os.path.exists in the exists function to use os.path.lexists instead.

I'm not sure which would be preferable to prevent this infinite loop.

*I came across this issue because collectstatic had been run both inside and outside a Vagrant box, so symlinks created inside the box did not exist when collectstatic was then run outside.

Change History (8)

comment:1 by Tim Graham, 7 years ago

Summary: Infinite loop in collectstaticInfinite loop in collectstatic with broken symlinks
Triage Stage: UnreviewedAccepted

comment:2 by KwonHan Bae, 7 years ago

I think its fixed in master branch.
should we backport to 11.x ?

comment:3 by Tim Graham, 7 years ago

Which commit fixed it? Most likely a fix wouldn't qualify for a backport based on our supported versions policy.

comment:4 by ChillarAnand, 6 years ago

Owner: changed from nobody to ChillarAnand
Status: newassigned

comment:5 by Jacob Walls, 3 years ago

Owner: changed from ChillarAnand to Jacob Walls
Version: 1.11dev

Decided to reproduce this on main. Still can.

I'm preparing a tiny patch using the second possibility from the ticket description: using os.path.lexists() in FileSystemStorage.exists().

comment:6 by Jacob Walls, 3 years ago

Component: contrib.staticfilesFile uploads/storage
Has patch: set

I reproduced this outside of contrib.staticfiles by just providing a broken symlink to FileSystemStorage.save() and never exiting a while loop. I'm hoping this is a welcome root cause to look at.

PR

comment:7 by Mariusz Felisiak, 3 years ago

Triage Stage: AcceptedReady for checkin

comment:8 by Mariusz Felisiak <felisiak.mariusz@…>, 3 years ago

Resolution: fixed
Status: assignedclosed

In ec2727ef:

Fixed #28154 -- Prevented infinite loop in FileSystemStorage.save() when a broken symlink with the same name exists.

Note: See TracTickets for help on using tickets.
Back to Top