Older malloc() implementations of UNIX used sbrk()/brk() system calls. But these days, implementations use mmap() and sbrk().  The malloc() implementation of glibc (that's probably the one you use on your Ubuntu 14.04) uses both sbrk() and mmap() and the choice to use which one to allocate when you request the typically depends on the size of the allocation request, which glibc does dynamically.
For small allocations, glibc uses sbrk() and for larger allocations it uses mmap(). The macro M_MMAP_THRESHOLD is used to decide this. Currently, it's default value is set to 128K. This explains why your code managed to allocate 135152 bytes as it is roughly ~128K. Even though, you requested only 1 byte, your implementation allocates 128K for efficient memory allocation. So segfault didn't occur until you cross this limit.
You can play with M_MAP_THRESHOLD by using mallopt() by changing the default parameters.
M_MMAP_THRESHOLD   
For allocations greater than or equal to the limit
  specified (in bytes) by M_MMAP_THRESHOLD that can't be satisfied  from
  the free list, the memory-allocation functions employ mmap(2) instead
  of increasing the program break using sbrk(2).
Allocating  memory  using  mmap(2)  has the significant advantage that
  the allocated memory blocks can always be independently released back
  to the system.  (By contrast, the heap can be trimmed only if memory
  is freed at the top  end.)   On  the  other hand,  there are some
  disadvantages to the use of mmap(2): deallocated space is not placed
  on the free list for reuse by later allocations; memory may be wasted
  because mmap(2) allocations must be page-aligned; and the kernel must
  perform the  expensive task  of  zeroing  out  memory  allocated via
  mmap(2).  Balancing these factors leads to a default setting of
  128*1024 for the M_MMAP_THRESHOLD parameter.
The lower limit for this parameter is 0.  The upper  limit  is 
  DEFAULT_MMAP_THRESHOLD_MAX:  512*1024  on  32-bit  systems  or
  4*1024*1024*sizeof(long) on 64-bit systems.
Note:  Nowadays,  glibc  uses  a  dynamic mmap threshold by default. 
  The initial value of the threshold is 128*1024, but when  blocks
  larger than the current threshold and less than or equal to
  DEFAULT_MMAP_THRESHOLD_MAX  are  freed,  the  threshold  is adjusted 
  upward  to the size of the freed block.  When dynamic mmap
  thresholding is in effect, the threshold for trimming the heap is also
  dynamically adjusted to be twice the dynamic mmap threshold.  Dynamic
  adjustment of the mmap  threshold  is  disabled if any of the
  M_TRIM_THRESHOLD, M_TOP_PAD, M_MMAP_THRESHOLD, or M_MMAP_MAX
  parameters is set.
For example, if you do:
#include<malloc.h>
mallopt(M_MMAP_THRESHOLD, 0);
before calling malloc(), you'll likely see a different limit. Most of these are implementation details and C standard says it's undefined behaviour to write into memory that your process doesn't own. So do it at your risk -- otherwise, demons may fly out of your nose ;-)