From patchwork Tue Aug 31 22:53:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 63325 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id C1252B715A for ; Wed, 1 Sep 2010 08:53:55 +1000 (EST) Received: (qmail 31921 invoked by alias); 31 Aug 2010 22:53:51 -0000 Received: (qmail 31910 invoked by uid 22791); 31 Aug 2010 22:53:48 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, TW_VB, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.35) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 31 Aug 2010 22:53:43 +0000 Received: from kpbe20.cbf.corp.google.com (kpbe20.cbf.corp.google.com [172.25.105.84]) by smtp-out.google.com with ESMTP id o7VMrebF019765 for ; Tue, 31 Aug 2010 15:53:41 -0700 Received: from gxk1 (gxk1.prod.google.com [10.202.11.1]) by kpbe20.cbf.corp.google.com with ESMTP id o7VMr3E7012735 for ; Tue, 31 Aug 2010 15:53:39 -0700 Received: by gxk1 with SMTP id 1so4075489gxk.40 for ; Tue, 31 Aug 2010 15:53:39 -0700 (PDT) Received: by 10.100.194.13 with SMTP id r13mr7193077anf.44.1283295219386; Tue, 31 Aug 2010 15:53:39 -0700 (PDT) Received: from coign.google.com (dhcp-172-22-124-178.mtv.corp.google.com [172.22.124.178]) by mx.google.com with ESMTPS id w10sm10404473ank.14.2010.08.31.15.53.38 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 31 Aug 2010 15:53:38 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: [gccgo] Verify that array lengths are reasonable Date: Tue, 31 Aug 2010 15:53:36 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch adds support to gccgo for verifying that array lengths are reasonable, rather than just accepting any old thing and crashing later. Committed to gccgo branch. Ian diff -r c59e94784c63 go/types.cc --- a/go/types.cc Tue Aug 31 15:01:07 2010 -0700 +++ b/go/types.cc Tue Aug 31 15:50:24 2010 -0700 @@ -3363,6 +3363,98 @@ return TRAVERSE_CONTINUE; } +// Check that the length is valid. + +bool +Array_type::verify_length() +{ + if (this->length_ == NULL) + return true; + if (!this->length_->is_constant()) + { + error_at(this->length_->location(), "array bound is not constant"); + return false; + } + + mpz_t val; + + Type* t = this->length_->type(); + if (t->integer_type() != NULL) + { + Type* vt; + mpz_init(val); + if (!this->length_->integer_constant_value(true, val, &vt)) + { + error_at(this->length_->location(), + "array bound is not constant"); + mpz_clear(val); + return false; + } + } + else if (t->float_type() != NULL) + { + Type* vt; + mpfr_t fval; + mpfr_init(fval); + if (!this->length_->float_constant_value(fval, &vt)) + { + error_at(this->length_->location(), + "array bound is not constant"); + mpfr_clear(fval); + return false; + } + if (!mpfr_integer_p(fval)) + { + error_at(this->length_->location(), + "array bound truncated to integer"); + mpfr_clear(fval); + return false; + } + mpz_init(val); + mpfr_get_z(val, fval, GMP_RNDN); + mpfr_clear(fval); + } + else + { + error_at(this->length_->location(), "array bound is not numeric"); + return false; + } + + if (mpz_sgn(val) < 0) + { + error_at(this->length_->location(), "negative array bound"); + mpz_clear(val); + return false; + } + + Type* int_type = Type::lookup_integer_type("int"); + int tbits = int_type->integer_type()->bits(); + int vbits = mpz_sizeinbase(val, 2); + if (vbits + 1 > tbits) + { + error_at(this->length_->location(), "array bound overflows"); + mpz_clear(val); + return false; + } + + mpz_clear(val); + + return true; +} + +// Verify the type. + +bool +Array_type::do_verify() +{ + if (!this->verify_length()) + { + this->length_ = Expression::make_error(this->length_->location()); + return false; + } + return true; +} + // Array type hash code. unsigned int diff -r c59e94784c63 go/types.h --- a/go/types.h Tue Aug 31 15:01:07 2010 -0700 +++ b/go/types.h Tue Aug 31 15:50:24 2010 -0700 @@ -1944,6 +1944,9 @@ do_traverse(Traverse* traverse); bool + do_verify(); + + bool do_has_pointer() const { return this->length_ == NULL || this->element_type_->has_pointer(); @@ -1978,6 +1981,9 @@ do_export(Export*) const; private: + bool + verify_length(); + tree get_length_tree(Gogo*);