csn1: Validate recursive array max size during decoding

This way if CSN1 encoded bitstream contains more elements than what the
defintion expects it will fail instead of overflowing the decoded
buffer.

RA cap struct placed in unit test is taken from a real android phone
sending the value when attaching to the network. Then SGSN sends it back
and osmo-pcu would crash similar to unit test:
*** stack smashing detected ***: terminated
 Process terminating with default action of signal 6 (SIGABRT): dumping core
at 0x4C62CE5: raise (in /usr/lib/libc-2.31.so)
by 0x4C4C856: abort (in /usr/lib/libc-2.31.so)
by 0x4CA62AF: __libc_message (in /usr/lib/libc-2.31.so)
by 0x4D36069: __fortify_fail (in /usr/lib/libc-2.31.so)
by 0x4D36033: __stack_chk_fail (in /usr/lib/libc-2.31.so)
by 0x124706: testRAcap2(void*) (RLCMACTest.cpp:468)

Related: OS#4463
Change-Id: I9fe0e55e0a6a41ae2cc885fba490c1d4a186231e
diff --git a/src/csn1.c b/src/csn1.c
index 296bf6c..7172847 100644
--- a/src/csn1.c
+++ b/src/csn1.c
@@ -1278,9 +1278,10 @@
       case CSN_RECURSIVE_TARRAY:
       { /* Recursive way to specify an array of type: <lists> ::= { 1 <type> } ** 0 ;
          *  M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
-         * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)}
+         * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)}
          */
         gint16 nSizeElement = (gint16)(gint32)pDescr->value;
+        guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn);
         guint8  ElementCount = 0;
         pui8  = pui8DATA(data, pDescr->offset);
 
@@ -1292,6 +1293,12 @@
           remaining_bits_len--;
           ElementCount++;
 
+          if (ElementCount > nSizeArray)
+          {
+            LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray);
+            return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
+          }
+
           { /* unpack the following data structure */
             csnStream_t arT = *ar;
             gint16      Status;
@@ -1342,9 +1349,10 @@
       case CSN_RECURSIVE_TARRAY_1:
       { /* Recursive way to specify an array of type: <lists> ::= <type> { 1 <type> } ** 0 ;
          * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
-         * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)}
+         * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)}
          */
         gint16      nSizeElement = (gint16)(gint32)pDescr->value;
+        guint32     nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn);
         guint8       ElementCount = 0;
         csnStream_t arT          = *ar;
         gboolean     EndOfList    = FALSE;
@@ -1355,6 +1363,12 @@
         { /* get data element */
           ElementCount++;
 
+          if (ElementCount > nSizeArray)
+          {
+            LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray);
+            return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
+          }
+
           LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz);
 
           csnStreamInit(&arT, bit_offset, remaining_bits_len);