~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/optimizer/path/equivclass.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-02-05 18:13:52 UTC
  • mfrom: (1.1.10) (10.1.5 oneiric-proposed)
  • Revision ID: package-import@ubuntu.com-20130205181352-3kw4f94ilqklzm7c
Tags: 9.1.8-0ubuntu11.10
* New upstream security/bug fix release: (LP: #1116336)
  - Prevent execution of enum_recv from SQL
    The function was misdeclared, allowing a simple SQL command to crash the
    server.  In principle an attacker might be able to use it to examine the
    contents of server memory.  Our thanks to Sumit Soni (via Secunia SVCRP)
    for reporting this issue. (CVE-2013-0255)
  - See HISTORY/changelog.gz for the other bug fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
 
32
32
static EquivalenceMember *add_eq_member(EquivalenceClass *ec,
33
 
                          Expr *expr, Relids relids,
 
33
                          Expr *expr, Relids relids, Relids nullable_relids,
34
34
                          bool is_child, Oid datatype);
35
35
static void generate_base_implied_equalities_const(PlannerInfo *root,
36
36
                                                                           EquivalenceClass *ec);
105
105
        Expr       *item1;
106
106
        Expr       *item2;
107
107
        Relids          item1_relids,
108
 
                                item2_relids;
 
108
                                item2_relids,
 
109
                                item1_nullable_relids,
 
110
                                item2_nullable_relids;
109
111
        List       *opfamilies;
110
112
        EquivalenceClass *ec1,
111
113
                           *ec2;
162
164
                        return false;           /* RHS is non-strict but not constant */
163
165
        }
164
166
 
 
167
        /* Calculate nullable-relid sets for each side of the clause */
 
168
        item1_nullable_relids = bms_intersect(item1_relids,
 
169
                                                                                  restrictinfo->nullable_relids);
 
170
        item2_nullable_relids = bms_intersect(item2_relids,
 
171
                                                                                  restrictinfo->nullable_relids);
 
172
 
165
173
        /*
166
174
         * We use the declared input types of the operator, not exprType() of the
167
175
         * inputs, as the nominal datatypes for opfamily lookup.  This presumes
308
316
        else if (ec1)
309
317
        {
310
318
                /* Case 3: add item2 to ec1 */
311
 
                em2 = add_eq_member(ec1, item2, item2_relids, false, item2_type);
 
319
                em2 = add_eq_member(ec1, item2, item2_relids, item2_nullable_relids,
 
320
                                                        false, item2_type);
312
321
                ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
313
322
                ec1->ec_below_outer_join |= below_outer_join;
314
323
                /* mark the RI as associated with this eclass */
321
330
        else if (ec2)
322
331
        {
323
332
                /* Case 3: add item1 to ec2 */
324
 
                em1 = add_eq_member(ec2, item1, item1_relids, false, item1_type);
 
333
                em1 = add_eq_member(ec2, item1, item1_relids, item1_nullable_relids,
 
334
                                                        false, item1_type);
325
335
                ec2->ec_sources = lappend(ec2->ec_sources, restrictinfo);
326
336
                ec2->ec_below_outer_join |= below_outer_join;
327
337
                /* mark the RI as associated with this eclass */
348
358
                ec->ec_broken = false;
349
359
                ec->ec_sortref = 0;
350
360
                ec->ec_merged = NULL;
351
 
                em1 = add_eq_member(ec, item1, item1_relids, false, item1_type);
352
 
                em2 = add_eq_member(ec, item2, item2_relids, false, item2_type);
 
361
                em1 = add_eq_member(ec, item1, item1_relids, item1_nullable_relids,
 
362
                                                        false, item1_type);
 
363
                em2 = add_eq_member(ec, item2, item2_relids, item2_nullable_relids,
 
364
                                                        false, item2_type);
353
365
 
354
366
                root->eq_classes = lappend(root->eq_classes, ec);
355
367
 
447
459
 */
448
460
static EquivalenceMember *
449
461
add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
450
 
                          bool is_child, Oid datatype)
 
462
                          Relids nullable_relids, bool is_child, Oid datatype)
451
463
{
452
464
        EquivalenceMember *em = makeNode(EquivalenceMember);
453
465
 
454
466
        em->em_expr = expr;
455
467
        em->em_relids = relids;
 
468
        em->em_nullable_relids = nullable_relids;
456
469
        em->em_is_const = false;
457
470
        em->em_is_child = is_child;
458
471
        em->em_datatype = datatype;
608
621
                elog(ERROR, "volatile EquivalenceClass has no sortref");
609
622
 
610
623
        newem = add_eq_member(newec, copyObject(expr), pull_varnos((Node *) expr),
611
 
                                                  false, opcintype);
 
624
                                                  NULL, false, opcintype);
612
625
 
613
626
        /*
614
627
         * add_eq_member doesn't check for volatile functions, set-returning
755
768
                }
756
769
        }
757
770
 
758
 
        /* Find the constant member to use */
 
771
        /*
 
772
         * Find the constant member to use.  We prefer an actual constant to
 
773
         * pseudo-constants (such as Params), because the constraint exclusion
 
774
         * machinery might be able to exclude relations on the basis of generated
 
775
         * "var = const" equalities, but "var = param" won't work for that.
 
776
         */
759
777
        foreach(lc, ec->ec_members)
760
778
        {
761
779
                EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
763
781
                if (cur_em->em_is_const)
764
782
                {
765
783
                        const_em = cur_em;
766
 
                        break;
 
784
                        if (IsA(cur_em->em_expr, Const))
 
785
                                break;
767
786
                }
768
787
        }
769
788
        Assert(const_em != NULL);
788
807
                }
789
808
                process_implied_equality(root, eq_op, ec->ec_collation,
790
809
                                                                 cur_em->em_expr, const_em->em_expr,
791
 
                                                                 ec->ec_relids,
 
810
                                                                 bms_copy(ec->ec_relids),
 
811
                                                                 bms_union(cur_em->em_nullable_relids,
 
812
                                                                                   const_em->em_nullable_relids),
792
813
                                                                 ec->ec_below_outer_join,
793
814
                                                                 cur_em->em_is_const);
794
815
        }
843
864
                        }
844
865
                        process_implied_equality(root, eq_op, ec->ec_collation,
845
866
                                                                         prev_em->em_expr, cur_em->em_expr,
846
 
                                                                         ec->ec_relids,
 
867
                                                                         bms_copy(ec->ec_relids),
 
868
                                                                         bms_union(prev_em->em_nullable_relids,
 
869
                                                                                           cur_em->em_nullable_relids),
847
870
                                                                         ec->ec_below_outer_join,
848
871
                                                                         false);
849
872
                }
1248
1271
                                                                                leftem->em_expr,
1249
1272
                                                                                rightem->em_expr,
1250
1273
                                                                                bms_union(leftem->em_relids,
1251
 
                                                                                                  rightem->em_relids));
 
1274
                                                                                                  rightem->em_relids),
 
1275
                                                                                bms_union(leftem->em_nullable_relids,
 
1276
                                                                                           rightem->em_nullable_relids));
1252
1277
 
1253
1278
        /* Mark the clause as redundant, or not */
1254
1279
        rinfo->parent_ec = parent_ec;
1470
1495
                                left_type,
1471
1496
                                right_type,
1472
1497
                                inner_datatype;
1473
 
        Relids          inner_relids;
 
1498
        Relids          inner_relids,
 
1499
                                inner_nullable_relids;
1474
1500
        ListCell   *lc1;
1475
1501
 
1476
1502
        Assert(is_opclause(rinfo->clause));
1497
1523
                inner_datatype = left_type;
1498
1524
                inner_relids = rinfo->left_relids;
1499
1525
        }
 
1526
        inner_nullable_relids = bms_intersect(inner_relids,
 
1527
                                                                                  rinfo->nullable_relids);
1500
1528
 
1501
1529
        /* Scan EquivalenceClasses for a match to outervar */
1502
1530
        foreach(lc1, root->eq_classes)
1555
1583
                                                                                                   cur_ec->ec_collation,
1556
1584
                                                                                                   innervar,
1557
1585
                                                                                                   cur_em->em_expr,
1558
 
                                                                                                   inner_relids);
 
1586
                                                                                                   bms_copy(inner_relids),
 
1587
                                                                                        bms_copy(inner_nullable_relids));
1559
1588
                        if (process_equivalence(root, newrinfo, true))
1560
1589
                                match = true;
1561
1590
                }
1589
1618
                                left_type,
1590
1619
                                right_type;
1591
1620
        Relids          left_relids,
1592
 
                                right_relids;
 
1621
                                right_relids,
 
1622
                                left_nullable_relids,
 
1623
                                right_nullable_relids;
1593
1624
        ListCell   *lc1;
1594
1625
 
1595
1626
        /* Can't use an outerjoin_delayed clause here */
1605
1636
        rightvar = (Expr *) get_rightop(rinfo->clause);
1606
1637
        left_relids = rinfo->left_relids;
1607
1638
        right_relids = rinfo->right_relids;
 
1639
        left_nullable_relids = bms_intersect(left_relids,
 
1640
                                                                                 rinfo->nullable_relids);
 
1641
        right_nullable_relids = bms_intersect(right_relids,
 
1642
                                                                                  rinfo->nullable_relids);
1608
1643
 
1609
1644
        foreach(lc1, root->eq_classes)
1610
1645
        {
1690
1725
                                                                                                           cur_ec->ec_collation,
1691
1726
                                                                                                           leftvar,
1692
1727
                                                                                                           cur_em->em_expr,
1693
 
                                                                                                           left_relids);
 
1728
                                                                                                           bms_copy(left_relids),
 
1729
                                                                                         bms_copy(left_nullable_relids));
1694
1730
                                if (process_equivalence(root, newrinfo, true))
1695
1731
                                        matchleft = true;
1696
1732
                        }
1703
1739
                                                                                                           cur_ec->ec_collation,
1704
1740
                                                                                                           rightvar,
1705
1741
                                                                                                           cur_em->em_expr,
1706
 
                                                                                                           right_relids);
 
1742
                                                                                                           bms_copy(right_relids),
 
1743
                                                                                        bms_copy(right_nullable_relids));
1707
1744
                                if (process_equivalence(root, newrinfo, true))
1708
1745
                                        matchright = true;
1709
1746
                        }
1829
1866
                        {
1830
1867
                                /* Yes, generate transformed child version */
1831
1868
                                Expr       *child_expr;
 
1869
                                Relids          new_nullable_relids;
1832
1870
 
1833
1871
                                child_expr = (Expr *)
1834
1872
                                        adjust_appendrel_attrs((Node *) cur_em->em_expr,
1835
1873
                                                                                   appinfo);
1836
 
                                (void) add_eq_member(cur_ec, child_expr, child_rel->relids,
 
1874
 
 
1875
                                /*
 
1876
                                 * Must translate nullable_relids.  Note this code assumes
 
1877
                                 * parent and child relids are singletons.
 
1878
                                 */
 
1879
                                new_nullable_relids = cur_em->em_nullable_relids;
 
1880
                                if (bms_overlap(new_nullable_relids, parent_rel->relids))
 
1881
                                {
 
1882
                                        new_nullable_relids = bms_difference(new_nullable_relids,
 
1883
                                                                                                                 parent_rel->relids);
 
1884
                                        new_nullable_relids = bms_add_members(new_nullable_relids,
 
1885
                                                                                                                  child_rel->relids);
 
1886
                                }
 
1887
 
 
1888
                                (void) add_eq_member(cur_ec, child_expr,
 
1889
                                                                         child_rel->relids, new_nullable_relids,
1837
1890
                                                                         true, cur_em->em_datatype);
1838
1891
                        }
1839
1892
                }
1844
1897
/*
1845
1898
 * mutate_eclass_expressions
1846
1899
 *        Apply an expression tree mutator to all expressions stored in
1847
 
 *        equivalence classes.
 
1900
 *        equivalence classes (but ignore child exprs unless include_child_exprs).
1848
1901
 *
1849
1902
 * This is a bit of a hack ... it's currently needed only by planagg.c,
1850
1903
 * which needs to do a global search-and-replace of MIN/MAX Aggrefs
1851
1904
 * after eclasses are already set up.  Without changing the eclasses too,
1852
 
 * subsequent matching of ORDER BY clauses would fail.
 
1905
 * subsequent matching of ORDER BY and DISTINCT clauses would fail.
1853
1906
 *
1854
1907
 * Note that we assume the mutation won't affect relation membership or any
1855
1908
 * other properties we keep track of (which is a bit bogus, but by the time
1859
1912
void
1860
1913
mutate_eclass_expressions(PlannerInfo *root,
1861
1914
                                                  Node *(*mutator) (),
1862
 
                                                  void *context)
 
1915
                                                  void *context,
 
1916
                                                  bool include_child_exprs)
1863
1917
{
1864
1918
        ListCell   *lc1;
1865
1919
 
1872
1926
                {
1873
1927
                        EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
1874
1928
 
 
1929
                        if (cur_em->em_is_child && !include_child_exprs)
 
1930
                                continue;               /* ignore children unless requested */
 
1931
 
1875
1932
                        cur_em->em_expr = (Expr *)
1876
1933
                                mutator((Node *) cur_em->em_expr, context);
1877
1934
                }