Skip to content

Commit

Permalink
fix: Crashing when files field is empty (#166)
Browse files Browse the repository at this point in the history
* Fix issue with managing challenges with an empty files section

---------

Signed-off-by: AlexNg <[email protected]>
  • Loading branch information
caffeine-addictt authored Dec 30, 2024
1 parent 763c2de commit d78a030
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions ctfcli/core/challenge.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,8 @@ def _load_challenge_id(self):
raise RemoteChallengeNotFound(f"Could not load remote challenge with name '{self['name']}'")

def _validate_files(self):
# if the challenge defines files, make sure they exist before making any changes to the challenge
for challenge_file in self.get("files", []):
files = self.get("files") or []
for challenge_file in files:
if not (self.challenge_directory / challenge_file).exists():
raise InvalidChallengeFile(f"File {challenge_file} could not be loaded")

Expand Down Expand Up @@ -364,7 +364,9 @@ def _create_file(self, local_path: Path):

def _create_all_files(self):
new_files = []
for challenge_file in self["files"]:

files = self.get("files") or []
for challenge_file in files:
new_files.append(("file", open(self.challenge_directory / challenge_file, mode="rb")))

files_payload = {"challenge_id": self.challenge_id, "type": "challenge"}
Expand Down Expand Up @@ -587,9 +589,12 @@ def sync(self, ignore: Tuple[str] = ()) -> None:

# Create / Upload files
if "files" not in ignore:
self["files"] = self.get("files") or []
remote_challenge["files"] = remote_challenge.get("files") or []

# Get basenames of local files to compare against remote files
local_files = {f.split("/")[-1]: f for f in self.get("files", [])}
remote_files = self._normalize_remote_files(remote_challenge.get("files", []))
local_files = {f.split("/")[-1]: f for f in self["files"]}
remote_files = self._normalize_remote_files(remote_challenge["files"])

# Delete remote files which are no longer defined locally
for remote_file in remote_files:
Expand Down Expand Up @@ -761,8 +766,8 @@ def lint(self, skip_hadolint=False, flag_format="flag{") -> bool:
click.secho("Skipping Hadolint", fg="yellow")

# Check that all files exist
challenge_files = challenge.get("files", [])
for challenge_file in challenge_files:
files = self.get("files") or []
for challenge_file in files:
challenge_file_path = self.challenge_directory / challenge_file

if challenge_file_path.is_file() is False:
Expand All @@ -771,8 +776,7 @@ def lint(self, skip_hadolint=False, flag_format="flag{") -> bool:
)

# Check that files don't have a flag in them
challenge_files = challenge.get("files", [])
for challenge_file in challenge_files:
for challenge_file in files:
challenge_file_path = self.challenge_directory / challenge_file

if not challenge_file_path.exists():
Expand All @@ -794,9 +798,12 @@ def mirror(self, files_directory_name: str = "dist", ignore: Tuple[str] = ()) ->
remote_challenge = self.load_installed_challenge(self.challenge_id)
challenge = self._normalize_challenge(remote_challenge)

remote_challenge["files"] = remote_challenge.get("files") or []
challenge["files"] = challenge.get("files") or []

# Add files which are not handled in _normalize_challenge
if "files" not in ignore:
local_files = {Path(f).name: f for f in challenge.get("files", [])}
local_files = {Path(f).name: f for f in challenge["files"]}

# Update files
for remote_file in remote_challenge["files"]:
Expand All @@ -813,9 +820,6 @@ def mirror(self, files_directory_name: str = "dist", ignore: Tuple[str] = ()) ->
challenge_files_directory.mkdir(parents=True, exist_ok=True)

(challenge_files_directory / remote_file_name).write_bytes(r.content)
if "files" not in challenge:
challenge["files"] = []

challenge["files"].append(f"{files_directory_name}/{remote_file_name}")

# The file is already present in the challenge.yml - we know the desired path
Expand All @@ -827,7 +831,7 @@ def mirror(self, files_directory_name: str = "dist", ignore: Tuple[str] = ()) ->
# Soft-Delete files that are not present on the remote
# Remove them from challenge.yml but do not delete them from disk
remote_file_names = [f.split("/")[-1].split("?token=")[0] for f in remote_challenge["files"]]
challenge["files"] = [f for f in challenge.get("files", []) if Path(f).name in remote_file_names]
challenge["files"] = [f for f in challenge["files"] if Path(f).name in remote_file_names]

for key in challenge.keys():
if key not in ignore:
Expand All @@ -841,6 +845,9 @@ def verify(self, ignore: Tuple[str] = ()) -> bool:
remote_challenge = self.load_installed_challenge(self.challenge_id)
normalized_challenge = self._normalize_challenge(remote_challenge)

remote_challenge["files"] = remote_challenge.get("files") or []
challenge["files"] = challenge.get("files") or []

for key in normalized_challenge:
if key in ignore:
continue
Expand All @@ -865,7 +872,7 @@ def verify(self, ignore: Tuple[str] = ()) -> bool:
# Check if files defined in challenge.yml are present
try:
self._validate_files()
local_files = {Path(f).name: f for f in challenge.get("files", [])}
local_files = {Path(f).name: f for f in challenge["files"]}
except InvalidChallengeFile:
return False

Expand Down

0 comments on commit d78a030

Please sign in to comment.