iemejia commented on code in PR #3860:
URL: https://github.com/apache/avro/pull/3860#discussion_r3567358924


##########
lang/csharp/src/apache/main/Generic/GenericReader.cs:
##########
@@ -404,11 +404,38 @@ protected virtual object ReadArray(object reuse, 
ArraySchema writerSchema, Schem
             ArraySchema rs = (ArraySchema)readerSchema;
             object result = CreateArray(reuse, rs);
             int i = 0;
-            for (int n = (int)d.ReadArrayStart(); n != 0; n = 
(int)d.ReadArrayNext())
+            long minBytes = MinBytesPerElement(writerSchema.ItemSchema);
+            long total = 0;
+            for (long nl = d.ReadArrayStart(); nl != 0; nl = d.ReadArrayNext())
             {
-                if (GetArraySize(result) < (i + n)) ResizeArray(ref result, i 
+ n);
+                // Reject a block whose element count could not be backed by 
the
+                // bytes remaining (or, for zero-byte elements, that exceeds 
the
+                // item cap) before allocating for it. Checked on the raw long,
+                // which also avoids the int cast below overflowing.
+                total = EnsureCollectionAvailable(d, total, nl, minBytes);
+                int n = (int)nl;
+                // Preallocate only a bounded amount up front, then grow on 
demand
+                // below. On a non-seekable stream EnsureCollectionAvailable 
cannot
+                // bound the count, so resizing straight to i+n could allocate 
a
+                // huge array before any element is read; a truncated stream 
instead
+                // fails within Read() after a bounded growth. Blocks no 
larger than
+                // the cap keep the original single-resize fast path.
+                int prealloc = i + Math.Min(n, MaxCollectionPrealloc);
+                if (GetArraySize(result) < prealloc) ResizeArray(ref result, 
prealloc);
                 for (int j = 0; j < n; j++, i++)
                 {
+                    if (GetArraySize(result) <= i)
+                    {
+                        int current = GetArraySize(result);
+                        int grown = current + (current >> 1) + 1;
+                        if (grown <= i)
+                        {
+                            grown = i + 1;
+                        }
+
+                        ResizeArray(ref result, grown);

Review Comment:
   Fixed in the latest commit — the growth is now computed in `long` (avoiding 
int overflow) and clamped to `MaxCollectionStructural` (which is <= the runtime 
max array length). Since the validated element count never exceeds that cap, 
the clamp can't starve a legitimate collection, and `Array.Resize` is never 
handed an over-large/negative size.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to