| 1846 | } |
| 1847 | |
| 1848 | int64 read_varlong(int f, uchar min_bytes) |
| 1849 | { |
| 1850 | union { |
| 1851 | char b[9]; |
| 1852 | int64 x; |
| 1853 | } u; |
| 1854 | char b2[8]; |
| 1855 | int extra; |
| 1856 | |
| 1857 | #if SIZEOF_INT64 < 8 |
| 1858 | memset(u.b, 0, 8); |
| 1859 | #else |
| 1860 | u.x = 0; |
| 1861 | #endif |
| 1862 | read_buf(f, b2, min_bytes); |
| 1863 | memcpy(u.b, b2+1, min_bytes-1); |
| 1864 | extra = int_byte_extra[CVAL(b2, 0) / 4]; |
| 1865 | if (extra) { |
| 1866 | uchar bit = ((uchar)1<<(8-extra)); |
| 1867 | if (min_bytes + extra > (int)sizeof u.b) { |
| 1868 | rprintf(FERROR, "Overflow in read_varlong()\n"); |
| 1869 | exit_cleanup(RERR_STREAMIO); |
| 1870 | } |
| 1871 | read_buf(f, u.b + min_bytes - 1, extra); |
| 1872 | u.b[min_bytes + extra - 1] = CVAL(b2, 0) & (bit-1); |
| 1873 | #if SIZEOF_INT64 < 8 |
| 1874 | if (min_bytes + extra > 5 || u.b[4] || CVAL(u.b,3) & 0x80) { |
| 1875 | rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n"); |
| 1876 | exit_cleanup(RERR_UNSUPPORTED); |
| 1877 | } |
| 1878 | #endif |
| 1879 | } else |
| 1880 | u.b[min_bytes + extra - 1] = CVAL(b2, 0); |
| 1881 | #if SIZEOF_INT64 < 8 |
| 1882 | u.x = IVAL(u.b,0); |
| 1883 | #elif CAREFUL_ALIGNMENT |
| 1884 | u.x = IVAL64(u.b,0); |
| 1885 | #endif |
| 1886 | return u.x; |
| 1887 | } |
| 1888 | |
| 1889 | /* Read an int32 and verify lo <= v <= hi. On out-of-range, abort with a |
| 1890 | * protocol error naming "what". The bound is co-located with the read so it |
no test coverage detected