laforge submitted this change.
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(-)
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 change 41228. To unsubscribe, or for help writing mail filters, visit settings.