laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/pysim/+/41228?usp=email )

Change subject: runtime: check record/file size before write
......................................................................

runtime: check record/file size before write

When writing data to a transparent or linear fixed (record oriented)
and the data to write exceeds the record/file size, then the UICC will
respond with an error "6700: Checking errors - Wrong length"

In particular when the data is supplied as a JSON object and not as a
hex string, it may not be immediately obvious to the average user what
the problem actually is.

Let's check the record/file size before writing the data and raise an
exception in case the data excieeds the record/file size. Let's also
print an informative string message in case the data length is less
than the record/file size to make the user aware of unwritten bytes
at the end of a record/file.

Related: OS#6864
Change-Id: I7fa717d803ae79398d2c5daf92a7336be660c5ad
---
M pySim/runtime.py
1 file changed, 43 insertions(+), 0 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved




diff --git a/pySim/runtime.py b/pySim/runtime.py
index ab21912..597323f 100644
--- a/pySim/runtime.py
+++ b/pySim/runtime.py
@@ -514,6 +514,47 @@
         dec_data = self.selected_file.decode_hex(data)
         return (dec_data, sw)

+    def __get_writeable_size(self):
+        """ Determine the writable size (file or record) using the cached FCP 
parameters of the currently selected
+            file. Return None in case the writeable size cannot be determined 
(no FCP available, FCP lacks size
+            information).
+        """
+        fcp = self.selected_file_fcp
+        if not fcp:
+            return None
+
+        structure = fcp.get('file_descriptor', {}).get('file_descriptor_byte', 
{}).get('structure')
+        if not structure:
+            return None
+
+        if structure == 'transparent':
+            return fcp.get('file_size')
+        elif structure == 'linear_fixed':
+            return fcp.get('file_descriptor', {}).get('record_len')
+        else:
+            return None
+
+    def __check_writeable_size(self, data_len):
+        """ Guard against unsuccessful writes caused by attempts to write data 
that exceeds the file limits. """
+
+        writeable_size = self.__get_writeable_size()
+        if not writeable_size:
+            return
+
+        if isinstance(self.selected_file, TransparentEF):
+            writeable_name = "file"
+        elif isinstance(self.selected_file, LinFixedEF):
+            writeable_name = "record"
+        else:
+            writeable_name = "object"
+
+        if data_len > writeable_size:
+            raise TypeError("Data length (%u) exceeds %s size (%u) by %u 
bytes" %
+                            (data_len, writeable_name, writeable_size, 
data_len - writeable_size))
+        elif data_len < writeable_size:
+            log.warn("Data length (%u) less than %s size (%u), leaving %u 
unwritten bytes at the end of the %s" %
+                     (data_len, writeable_name, writeable_size, writeable_size 
- data_len, writeable_name))
+
     def update_binary(self, data_hex: str, offset: int = 0):
         """Update transparent EF binary data.

@@ -524,6 +565,7 @@
         if not isinstance(self.selected_file, TransparentEF):
             raise TypeError("Only works with TransparentEF, but %s is %s" % 
(self.selected_file,
                                                                              
self.selected_file.__class__.__mro__))
+        self.__check_writeable_size(len(data_hex) // 2 + offset)
         return self.scc.update_binary(self.selected_file.fid, data_hex, 
offset, conserve=self.rs.conserve_write)

     def update_binary_dec(self, data: dict):
@@ -571,6 +613,7 @@
         if not isinstance(self.selected_file, LinFixedEF):
             raise TypeError("Only works with Linear Fixed EF, but %s is %s" % 
(self.selected_file,
                                                                                
self.selected_file.__class__.__mro__))
+        self.__check_writeable_size(len(data_hex) // 2)
         return self.scc.update_record(self.selected_file.fid, rec_nr, data_hex,
                                               conserve=self.rs.conserve_write,
                                               
leftpad=self.selected_file.leftpad)

--
To view, visit https://gerrit.osmocom.org/c/pysim/+/41228?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I7fa717d803ae79398d2c5daf92a7336be660c5ad
Gerrit-Change-Number: 41228
Gerrit-PatchSet: 4
Gerrit-Owner: dexter <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>

Reply via email to