Skip to content

Commit eaaf811

Browse files
committed
fix: narrow exception handling and bound expansion cache size
- artifact_exporter.py: catch InvalidSamDocumentException instead of bare Exception so programming bugs propagate instead of being silently swallowed - sam_integration.py: add _MAX_CACHE_SIZE=32 with FIFO eviction to prevent unbounded memory growth in long-running processes (sam sync --watch)
1 parent 115dbed commit eaaf811

2 files changed

Lines changed: 14 additions & 5 deletions

File tree

samcli/lib/cfn_language_extensions/sam_integration.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
# Module-level cache for expand_language_extensions() results.
3838
# Key: (template_path, file_mtime, parameter_values_hash)
3939
_expansion_cache: Dict[Tuple[str, float, str], "LanguageExtensionResult"] = {}
40+
_MAX_CACHE_SIZE = 32
4041

4142

4243
def _hash_params(parameter_values: Optional[Dict[str, Any]]) -> str:
@@ -61,6 +62,13 @@ def clear_expansion_cache() -> None:
6162
_expansion_cache.clear()
6263

6364

65+
def _cache_put(key: Tuple[str, float, str], value: "LanguageExtensionResult") -> None:
66+
"""Store a result in the expansion cache, evicting the oldest entry if full."""
67+
if len(_expansion_cache) >= _MAX_CACHE_SIZE:
68+
_expansion_cache.pop(next(iter(_expansion_cache)))
69+
_expansion_cache[key] = value
70+
71+
6472
@dataclass(frozen=True)
6573
class LanguageExtensionResult:
6674
"""
@@ -560,12 +568,12 @@ def expand_language_extensions(
560568
)
561569
if cache_key is not None:
562570
# Store a deep copy so callers can't poison the cache
563-
_expansion_cache[cache_key] = LanguageExtensionResult(
571+
_cache_put(cache_key, LanguageExtensionResult(
564572
expanded_template=copy.deepcopy(result.expanded_template),
565573
original_template=copy.deepcopy(result.original_template),
566574
dynamic_artifact_properties=list(result.dynamic_artifact_properties),
567575
had_language_extensions=result.had_language_extensions,
568-
)
576+
))
569577
return result
570578

571579
LOG.debug("Expanding CloudFormation Language Extensions (Phase 1)")
@@ -601,12 +609,12 @@ def expand_language_extensions(
601609

602610
if cache_key is not None:
603611
# Store a deep copy so callers can't poison the cache
604-
_expansion_cache[cache_key] = LanguageExtensionResult(
612+
_cache_put(cache_key, LanguageExtensionResult(
605613
expanded_template=copy.deepcopy(result.expanded_template),
606614
original_template=copy.deepcopy(result.original_template),
607615
dynamic_artifact_properties=list(result.dynamic_artifact_properties),
608616
had_language_extensions=result.had_language_extensions,
609-
)
617+
))
610618

611619
return result
612620

samcli/lib/package/artifact_exporter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
from samcli.commands._utils.experimental import ExperimentalFlag, is_experimental_enabled
2424
from samcli.commands.package import exceptions
25+
from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
2526
from samcli.lib.cfn_language_extensions.utils import iter_regular_resources
2627
from samcli.lib.package.code_signer import CodeSigner
2728
from samcli.lib.package.local_files_utils import get_uploaded_s3_object_name, mktempfile
@@ -107,7 +108,7 @@ def do_export(self, resource_id, resource_dict, parent_dir):
107108

108109
try:
109110
result = expand_language_extensions(child_template_dict, parameter_values, template_path=abs_template_path)
110-
except Exception:
111+
except InvalidSamDocumentException:
111112
LOG.debug("Language extensions expansion failed for %s, using original template", abs_template_path)
112113
result = None
113114

0 commit comments

Comments
 (0)