diff --git a/reai_toolkit/app/components/dialogs/analyse_dialog.py b/reai_toolkit/app/components/dialogs/analyse_dialog.py index ee3f8ac..82c66d4 100644 --- a/reai_toolkit/app/components/dialogs/analyse_dialog.py +++ b/reai_toolkit/app/components/dialogs/analyse_dialog.py @@ -177,13 +177,23 @@ def _on_ok(self) -> None: file_path=self.file_path, symbols=AnalyseDialog.cached_symbols, debug_file_path=self.debug_file_path, - tags=[], + tags=self._parse_tags(), public=self.ui.radioButton_2.isChecked(), thread_callback=self.callback, ) self.accept() + def _parse_tags(self) -> list[str]: + seen: set[str] = set() + tags: list[str] = [] + for raw in self.ui.apiTags.text().split(","): + tag: str = raw.strip() + if tag and tag not in seen: + seen.add(tag) + tags.append(tag) + return tags + def initialize_function_boundaries(self) -> None: symbols: Symbols | None = collect_symbols_from_ida() if symbols is None: diff --git a/reai_toolkit/app/services/upload/upload_service.py b/reai_toolkit/app/services/upload/upload_service.py index ab47f59..ad0b64c 100644 --- a/reai_toolkit/app/services/upload/upload_service.py +++ b/reai_toolkit/app/services/upload/upload_service.py @@ -10,6 +10,7 @@ from revengai.models.analysis_create_request import AnalysisCreateRequest from revengai.models.analysis_create_response import AnalysisCreateResponse from revengai.models.analysis_scope import AnalysisScope +from revengai.models.tag import Tag from revengai.models.upload_file_type import UploadFileType from revengai.models.base_response_upload_response import BaseResponseUploadResponse @@ -212,7 +213,7 @@ def analyse( filename=file_name, sha_256_hash=binary_sha256, debug_hash=debug_sha256, - tags=tags or [], + tags=[Tag(name=tag) for tag in (tags or [])], analysis_scope=AnalysisScope.PUBLIC if public else AnalysisScope.PRIVATE, symbols=symbols, ) diff --git a/tests/unit/upload/test_service.py b/tests/unit/upload/test_service.py index 6e29a8b..d1d3afe 100644 --- a/tests/unit/upload/test_service.py +++ b/tests/unit/upload/test_service.py @@ -1,6 +1,9 @@ from unittest.mock import MagicMock import pytest +from revengai.models.function_boundary import FunctionBoundary +from revengai.models.symbols import Symbols +from revengai.models.tag import Tag from revengai.models.upload_file_type import UploadFileType from reai_toolkit.app.services.upload import upload_service as svc_mod @@ -22,6 +25,16 @@ def sdk(mocker): return api_inst +@pytest.fixture +def symbols(): + return Symbols( + base_address=0, + function_boundaries=[ + FunctionBoundary(mangled_name="main", start_address=0, end_address=16) + ], + ) + + def test_upload_file_passes_tuple_to_sdk(service, sdk): result = service._upload_file_req( upload_file_type=UploadFileType.BINARY, @@ -55,3 +68,24 @@ def test_upload_file_defaults_force_overwrite_false(service, sdk): ) assert sdk.upload_file.call_args.kwargs["force_overwrite"] is False + + +@pytest.mark.parametrize( + "tags, expected", + [ + (["malware", "linux", "trojan"], ["malware", "linux", "trojan"]), + (["solo"], ["solo"]), + ([], []), + (None, []), + ], +) +def test_analyse_converts_tags_to_tag_models(service, sdk, symbols, tags, expected): + service.analyse( + file_name="binary.elf", + binary_sha256="deadbeef", + symbols=symbols, + tags=tags, + ) + + request = sdk.create_analysis.call_args.kwargs["analysis_create_request"] + assert request.tags == [Tag(name=name) for name in expected]