Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

qsort.c

Blame
    • Tom Lane's avatar
      9d6077ab
      Fix a low-probability crash in our qsort implementation. · 9d6077ab
      Tom Lane authored
      It's standard for quicksort implementations, after having partitioned the
      input into two subgroups, to recurse to process the smaller partition and
      then handle the larger partition by iterating.  This method guarantees
      that no more than log2(N) levels of recursion can be needed.  However,
      Bentley and McIlroy argued that checking to see which partition is smaller
      isn't worth the cycles, and so their code doesn't do that but just always
      recurses on the left partition.  In most cases that's fine; but with
      worst-case input we might need O(N) levels of recursion, and that means
      that qsort could be driven to stack overflow.  Such an overflow seems to
      be the only explanation for today's report from Yiqing Jin of a SIGSEGV
      in med3_tuple while creating an index of a couple billion entries with a
      very large maintenance_work_mem setting.  Therefore, let's spend the few
      additional cycles and lines of code needed to choose the smaller partition
      for recursion.
      
      Also, fix up the qsort code so that it properly uses size_t not int for
      some intermediate values representing numbers of items.  This would only
      be a live risk when sorting more than INT_MAX bytes (in qsort/qsort_arg)
      or tuples (in qsort_tuple), which I believe would never happen with any
      caller in the current core code --- but perhaps it could happen with
      call sites in third-party modules?  In any case, this is trouble waiting
      to happen, and the corrected code is probably if anything shorter and
      faster than before, since it removes sign-extension steps that had to
      happen when converting between int and size_t.
      
      In passing, move a couple of CHECK_FOR_INTERRUPTS() calls so that it's
      not necessary to preserve the value of "r" across them, and prettify
      the output of gen_qsort_tuple.pl a little.
      
      Back-patch to all supported branches.  The odds of hitting this issue
      are probably higher in 9.4 and up than before, due to the new ability
      to allocate sort workspaces exceeding 1GB, but there's no good reason
      to believe that it's impossible to crash older branches this way.
      9d6077ab
      History
      Fix a low-probability crash in our qsort implementation.
      Tom Lane authored
      It's standard for quicksort implementations, after having partitioned the
      input into two subgroups, to recurse to process the smaller partition and
      then handle the larger partition by iterating.  This method guarantees
      that no more than log2(N) levels of recursion can be needed.  However,
      Bentley and McIlroy argued that checking to see which partition is smaller
      isn't worth the cycles, and so their code doesn't do that but just always
      recurses on the left partition.  In most cases that's fine; but with
      worst-case input we might need O(N) levels of recursion, and that means
      that qsort could be driven to stack overflow.  Such an overflow seems to
      be the only explanation for today's report from Yiqing Jin of a SIGSEGV
      in med3_tuple while creating an index of a couple billion entries with a
      very large maintenance_work_mem setting.  Therefore, let's spend the few
      additional cycles and lines of code needed to choose the smaller partition
      for recursion.
      
      Also, fix up the qsort code so that it properly uses size_t not int for
      some intermediate values representing numbers of items.  This would only
      be a live risk when sorting more than INT_MAX bytes (in qsort/qsort_arg)
      or tuples (in qsort_tuple), which I believe would never happen with any
      caller in the current core code --- but perhaps it could happen with
      call sites in third-party modules?  In any case, this is trouble waiting
      to happen, and the corrected code is probably if anything shorter and
      faster than before, since it removes sign-extension steps that had to
      happen when converting between int and size_t.
      
      In passing, move a couple of CHECK_FOR_INTERRUPTS() calls so that it's
      not necessary to preserve the value of "r" across them, and prettify
      the output of gen_qsort_tuple.pl a little.
      
      Back-patch to all supported branches.  The odds of hitting this issue
      are probably higher in 9.4 and up than before, due to the new ability
      to allocate sort workspaces exceeding 1GB, but there's no good reason
      to believe that it's impossible to crash older branches this way.
    qsort.c 6.21 KiB